Substrings POJ - 1226 (后缀数组)

You are given a number of case-sensitive strings of alphabetic characters, find the largest string X, such that either X, or its inverse can be found as a substring of any of the given strings.

Input

The first line of the input contains a single integer t (1 <= t <= 10), the number of test cases, followed by the input data for each test case. The first line of each test case contains a single integer n (1 <= n <= 100), the number of given strings, followed by n lines, each representing one string of minimum length 1 and maximum length 100. There is no extra white space before and after a string.

Output

There should be one line per test case containing the length of the largest string found.

Sample Input

2
3
ABCD
BCDFF
BRCD
2
rose
orchid

Sample Output

2
2 

题意:求出所有串中,最长的子串长度(子串不一定要相等,子串反转后相等也行)

思路:二分子串长度,将每个串和其反串合并成一个数组,然后求后缀数组,并记录每个串长度前缀和(长度前缀和指的是加上该串和其反串后整个字符长)
然后对于ht数组,如果当前ht数组所对应的sa【i】和sa【i-1】出现的串之前没出现过,那么种类数+1,直到种类数 == n
如果中途发现ht < mid 那么就清空之前所记录的信息,重新匹配


  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<algorithm>
  6 using namespace std;
  7 
  8 int T,n;
  9 const int maxn = 2e5+5;
 10 string s;
 11 int sa[maxn],t[maxn],t2[maxn],c[maxn],len[105];
 12 
 13 void build_sa(int n,int m)
 14 {
 15     int i,*x=t,*y=t2;
 16     for(i=0; i<m; i++)c[i]=0;
 17     for(i=0; i<n; i++)c[x[i]=s[i]]++;
 18     for(i=1; i<m; i++)c[i]+=c[i-1];
 19     for(i=n-1; i>=0; i--)sa[--c[x[i]]]=i;
 20     for(int k=1; k<=n; k<<=1)
 21     {
 22         int p=0;
 23         for(i=n-k; i<n; i++)y[p++]=i;
 24         for(i=0; i<n; i++)if(sa[i] >= k)y[p++]=sa[i]-k;
 25         for(i=0; i<m; i++)c[i] = 0;
 26         for(i=0; i<n; i++)c[x[y[i]]]++;
 27         for(i=1; i<m; i++)c[i]+=c[i-1];
 28         for(i=n-1; i>=0; i--)sa[--c[x[y[i]]]] = y[i];
 29         swap(x,y);
 30         p=1,x[sa[0]]=0;
 31         for(i=1; i<n; i++)
 32             x[sa[i]] = y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k] == y[sa[i]+k]?p-1:p++;
 33         if(p>=n)break;
 34         m=p;
 35     }
 36 }
 37 
 38 int ht[maxn],rk[maxn];
 39 
 40 void getHeight(int n)
 41 {
 42     int i,j,k=0;
 43     for(i=0; i<n; i++)rk[sa[i]] = i;
 44     for(i=0; i<n-1; i++)
 45     {
 46         if(k)k--;
 47         if(s[i] == '$')continue;
 48         int j = sa[rk[i]-1];
 49         while(s[i+k] == s[j+k] && s[i+k] != '$')k++;
 50         ht[rk[i]] = k;
 51     }
 52 }
 53 
 54 bool vis[105];
 55 bool check(int mid)
 56 {
 57     memset(vis,0,sizeof(vis));
 58     int cnt=0;
 59     bool flag = 0;
 60     for(int i=1; i<len[n]; i++)
 61     {
 62         if(ht[i] >= mid && s[sa[i]] != '$')
 63         {
 64 
 65             for(int j=1; j<=n; j++)
 66             {
 67                 if(!flag)
 68                 {
 69                     //printf("%d $$$$ %d    %d\n",sa[i-1]+1,len[j-1],len[j]);
 70                     if(sa[i-1]+1 > len[j-1] && sa[i-1]+1 < len[j])if(!vis[j])vis[j]=1,cnt++,flag = 1;
 71                 }
 72                 if(sa[i]+1 > len[j-1] && sa[i]+1 < len[j])if(!vis[j])vis[j] = 1,cnt++;
 73             }
 74           //  printf("============================================\n",flag);
 75         }
 76         else
 77         {
 78             if(cnt == n)return 1;
 79             cnt = 0;
 80             flag = 0;
 81             memset(vis,0,sizeof(vis));
 82         }
 83     }
 84     if(cnt == n)return 1;
 85     return 0;
 86 }
 87 char tmp[200];
 88 int main()
 89 {
 90     scanf("%d",&T);
 91     while(T--)
 92     {
 93         scanf("%d",&n);
 94         s.clear();
 95         for(int i=1; i<=n; i++)
 96         {
 97             scanf("%s",tmp);
 98             int tmp_len = strlen(tmp);
 99             s+=tmp;
100             s+='$';
101             reverse(tmp,tmp+tmp_len);
102             s+=tmp;
103             s+='$';
104             len[i] = s.length();
105         }
106        // for(int i=1;i<=n;i++)printf("%d =========\n",len[i]);
107 //        if(n == 1)
108 //        {
109 //            printf("%d\n",len[1]/2-1);
110 //            continue;
111 //        }
112         build_sa(len[n],130);
113         getHeight(len[n]);
114         int L = 1,R = len[n];
115         int pos = 0;
116         while(L <= R)
117         {
118             int mid = (L+R)/2;
119             if(check(mid))pos = mid,L=mid+1;
120             else R = mid-1;
121         }
122         cout << pos << endl;
123     }
124 
125 }
View Code

猜你喜欢

转载自www.cnblogs.com/iwannabe/p/11483455.html