poj1226 Substrings

2333

这个就是把每一个串正反连起来,然后所有串连起来,注意中间加上分割的分开(应该开的比z大,而且蛋疼的我写int)

然后搞出后缀数组,二分一个答案,然后再height数组判断一下就好了

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <cstring>
  4 #define N 100005
  5 #define inf 0x3f3f3f3f
  6 #define LL long long
  7 #define eps 1e-8
  8 using namespace std;
  9 inline int ra()
 10 {
 11     int x=0,f=1; char ch=getchar();
 12     while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
 13     while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
 14     return x*f;
 15 }
 16 
 17 const int maxn=10005;
 18 
 19 int sa[2][maxn],rank[2][maxn],v[maxn],height[maxn],p=0,q=1;
 20 int n,len,id[maxn];
 21 int a[maxn];
 22 bool vis[105];
 23 
 24 void cal_sa(int sa[N], int rank[N], int Sa[N], int Rank[N], int k)
 25 {
 26     for (int i=1; i<=n; i++) v[rank[sa[i]]]=i;
 27     for (int i=n; i>=1; i--) if (sa[i]>k) Sa[v[rank[sa[i]-k]]--]=sa[i]-k;
 28     for (int i=n-k+1; i<=n; i++) Sa[v[rank[i]]--]=i;
 29     for (int i=1; i<=n; i++) Rank[Sa[i]]=Rank[Sa[i-1]]+(rank[Sa[i]]!=rank[Sa[i-1]] || rank[Sa[i]+k]!=rank[Sa[i-1]+k]);
 30 }
 31 void get_height()
 32 {
 33     int k=0;
 34     for (int i=1; i<=n; i++)
 35     {
 36         if (rank[p][i]==1) height[1]=0;
 37         else
 38         {
 39             int j=sa[p][rank[p][i]-1];
 40             while (a[j+k]==a[i+k]) k++;
 41             height[rank[p][i]]=k;
 42             if (k) k--;
 43         }
 44     }
 45 }
 46 void work()
 47 {
 48     for (int i=1; i<=n; i++) v[a[i]]++;
 49     for (int i=1; i<=300; i++) v[i]+=v[i-1];
 50     for (int i=1; i<=n; i++) sa[p][v[a[i]]--]=i;
 51     for (int i=1; i<=n; i++) rank[p][sa[p][i]]=rank[p][sa[p][i-1]]+(a[sa[p][i]]!=a[sa[p][i-1]]);
 52     for (int k=1; k<n; k<<=1,swap(p,q)) cal_sa(sa[p],rank[p],sa[q],rank[q],k);
 53     get_height();
 54 }
 55 
 56 bool check(int L)
 57 {
 58     int tot=0; memset(vis,0,sizeof(vis));
 59     for (int i=2; i<=n; i++)
 60     {
 61         if (height[i]<L)
 62         {
 63             tot=0; memset(vis,0,sizeof(vis));
 64             continue;
 65         }
 66         if (!vis[id[sa[p][i-1]]]) vis[id[sa[p][i-1]]]=1,tot++;
 67         if (!vis[id[sa[p][i]]]) vis[id[sa[p][i]]]=1,tot++;
 68         if (tot>=len) return 1;
 69     }
 70     return 0;
 71 }
 72 void solve()
 73 {
 74     int l=0,r=n,ans=0;
 75     while (l<=r)
 76     {
 77         int mid=l+r>>1;
 78         if (check(mid)) ans=mid,l=mid+1; else r=mid-1;
 79     }
 80     printf("%d\n",ans);
 81 }
 82 int main(int argc, char const *argv[])
 83 {
 84     int T=ra();
 85     while (T--)
 86     {
 87         memset(v,0,sizeof(v)); n=ra(); len=0;
 88         for (int i=1; i<=n; i++)
 89         {
 90             char ch[105]; scanf("%s",ch+1);
 91             for (int j=1; j<=strlen(ch+1); j++)
 92                 a[++len]=ch[j],id[len]=i;
 93             a[++len]=150+(i-1)*2,id[len]=i;
 94             for (int j=strlen(ch+1); j>=1; j--)
 95                 a[++len]=ch[j],id[len]=i;
 96             a[++len]=150+(i-1)*2+1,id[len]=i;
 97         }
 98         swap(n,len); work();
 99         solve();
100     }
101     return 0;
102 }

 

posted @ 2017-03-29 22:35  ws_ccd  阅读(190)  评论(0编辑  收藏  举报