(后缀数组)Codeforces Round #434 (Div. 2) D.Polycarp's phone book

B. Polycarp's phone book
time limit per test
4 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

There are n phone numbers in Polycarp's contacts on his phone. Each number is a 9-digit integer, starting with a digit different from 0. All the numbers are distinct.

There is the latest version of Berdroid OS installed on Polycarp's phone. If some number is entered, is shows up all the numbers in the contacts for which there is a substring equal to the entered sequence of digits. For example, is there are three phone numbers in Polycarp's contacts: 123456789, 100000000 and 100123456, then:

  • if he enters 00 two numbers will show up: 100000000 and 100123456,
  • if he enters 123 two numbers will show up 123456789 and 100123456,
  • if he enters 01 there will be only one number 100123456.

For each of the phone numbers in Polycarp's contacts, find the minimum in length sequence of digits such that if Polycarp enters this sequence, Berdroid shows this only phone number.

Input

The first line contains single integer n (1 ≤ n ≤ 70000) — the total number of phone contacts in Polycarp's contacts.

The phone numbers follow, one in each line. Each number is a positive 9-digit integer starting with a digit from 1 to 9. All the numbers are distinct.

Output

Print exactly n lines: the i-th of them should contain the shortest non-empty sequence of digits, such that if Polycarp enters it, the Berdroid OS shows up only the i-th number from the contacts. If there are several such sequences, print any of them.

Examples
Input
3
123456789
100000000
100123456
Output
9
000
01
Input
4
123456789
193456789
134567819
934567891
Output
2
193
81
91

先将所有串连起来,中间用0——9以外的数字(且两两不同)隔开,求sa、height数组。

扫一遍sa[i],对于每个sa[i],向前、向后找第一个出现的与其不是同一个串的位置,只需求这段height的RMQ,考虑到向左、向右最多走9步(实际上比这个少的多),直接用一个变量记录即可。

与sa[i]起始的串相同的其他串的子串最大长度为 向左、向右走种上述RMQ的较大的一个。

这样O(n)求完之后再扫一遍所有串,对于每个串,找其各个位置上述值的最小值(且需要符合题意,结尾+1不超过总长,因为最短的恰为公共长度+1),输出即可。

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <algorithm>
  4 #include <vector>
  5 #include <set>
  6 #include <map>
  7 #include <string>
  8 #include <cstring>
  9 #include <stack>
 10 #include <queue>
 11 #include <cmath>
 12 #include <ctime>
 13 #include <bitset>
 14 #include <utility>
 15 #include <assert.h>
 16 using namespace std;
 17 #define rank rankk
 18 #define mp make_pair
 19 #define pb push_back
 20 #define xo(a,b) ((b)&1?(a):0)
 21 #define tm tmp
 22 //#define LL ll
 23 typedef unsigned long long ull;
 24 typedef pair<int,int> pii;
 25 typedef long long ll;
 26 typedef pair<ll,int> pli;
 27 typedef pair<ll,ll> pll;
 28 const int INF=0x3f3f3f3f;
 29 const ll INFF=0x3f3f3f3f3f3f3f3fll;
 30 const int MAX=1e5+5;
 31 //const ll MAXN=2e8;
 32 //const int MAX_N=MAX;
 33 const ll MOD=1e9+7;
 34 //const long double pi=acos(-1.0);
 35 const long double eps=1e-9;
 36 int gcd(int a,int b){return b?gcd(b,a%b):a;}
 37 template<typename T>inline T abs(T a) {return a>0?a:-a;}
 38 template<class T> inline
 39 void read(T& num) {
 40     bool start=false,neg=false;
 41     char c;
 42     num=0;
 43     while((c=getchar())!=EOF) {
 44         if(c=='-') start=neg=true;
 45         else if(c>='0' && c<='9') {
 46             start=true;
 47             num=num*10+c-'0';
 48         } else if(start) break;
 49     }
 50     if(neg) num=-num;
 51 }
 52 inline ll powMM(ll a,ll b,ll M){
 53     ll ret=1;
 54     a%=M;
 55 //    b%=M;
 56     while (b){
 57         if (b&1) ret=ret*a%M;
 58         b>>=1;
 59         a=a*a%M;
 60     }
 61     return ret;
 62 }
 63 void open()
 64 {
 65 //    freopen("1009.in","r",stdin);
 66     freopen("out.txt","w",stdout);
 67 }
 68 
 69 const int MAXN=8e5;
 70 int t1[MAXN],t2[MAXN],c[MAXN];
 71 bool cmp(int *r,int a,int b,int l)
 72 {
 73     return r[a] == r[b] && r[a+l] == r[b+l];
 74 }
 75 void da(int str[],int sa[],int rank[],int height[],int n,int m)
 76 {
 77     str[n++]=0;
 78     int i, j, p, *x = t1, *y = t2;
 79     for(i = 0;i < m;i++)c[i] = 0;
 80     for(i = 0;i < n;i++)c[x[i] = str[i]]++;
 81     for(i = 1;i < m;i++)c[i] += c[i-1];
 82     for(i = n-1;i >= 0;i--)sa[--c[x[i]]] = i;
 83     for(j = 1;j <= n; j <<= 1)
 84     {
 85         p = 0;
 86         for(i = n-j; i < n; i++)y[p++] = i;
 87         for(i = 0; i < n; i++)if(sa[i] >= j)y[p++] = sa[i] - j;
 88         for(i = 0; i < m; i++)c[i] = 0;
 89         for(i = 0; i < n; i++)c[x[y[i]]]++;
 90         for(i = 1; i < m;i++)c[i] += c[i-1];
 91         for(i = n-1; i >= 0;i--)sa[--c[x[y[i]]]] = y[i];
 92         swap(x,y);
 93         p = 1; x[sa[0]] = 0;
 94         for(i = 1;i < n;i++)
 95             x[sa[i]] = cmp(y,sa[i-1],sa[i],j)?p-1:p++;
 96         if(p >= n)break;
 97         m = p;
 98     }
 99     int k = 0; n--;
100     for(i = 0;i <= n;i++)rank[sa[i]] = i;
101     for(i = 0;i < n;i++)
102     {
103         if(k)k--;
104         j = sa[rank[i]-1]; while(str[i+k] == str[j+k])k++; height[rank[i]] = k;
105     }
106 }
107 int rank[MAXN],height[MAXN];
108 int st[MAXN];
109 
110 int sa[MAXN];
111 int n,now,num[MAXN],lo,an,an1,an2;
112 char str[MAXN];
113 int main()
114 {
115     scanf("%d",&n);
116     now=0;
117     for(int i=1;i<=n;i++)
118     {
119         scanf("%s",str);
120         for(int j=0;j<9;j++)
121             st[now+j]=str[j]-'0'+1;
122         st[now+9]=11+i;
123         now+=10;
124     }
125     da(st,sa,rank,height,now,13+n);
126     for(int i=1;i<=now;i++)
127     {
128         int who=sa[i]/10;
129         int len=an1=an2=INF;
130         int sts=i;
131         while(sa[sts-1]/10==who)
132         {
133             an1=min(an1,height[sts]);--sts;
134         }
135         an1=min(an1,height[sts]);
136         int en=i+1;
137         while(sa[en]/10==who)
138         {
139             an2=min(an2,height[en]);
140             ++en;
141         }
142         an2=min(an2,height[en]);
143         if(an1==INF)an1=0;
144         if(an2==INF)an2=0;
145         len=max(an1,an2);
146         num[sa[i]]=len;
147     }
148     now=0,an=9;
149     for(int i=1;i<=n;i++)
150     {
151         lo=now;an=9;
152         for(int j=0;j<9;j++)
153         {
154             if(num[now+j]<an&&num[now+j]+j<9)
155             {
156                 an=num[now+j];lo=now+j;
157             }
158         }
159         for(int j=0;j<an+1;j++)
160             printf("%d",st[lo+j]-1);
161         printf("\n");
162         now+=10;
163     }
164     return 0;
165 }

 

posted @ 2017-09-18 10:39  perplex  阅读(457)  评论(0编辑  收藏  举报