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.
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.
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.
3
123456789
100000000
100123456
9
000
01
4
123456789
193456789
134567819
934567891
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(" "); 162 now+=10; 163 } 164 return 0; 165 }