• 【BZOJ】【2946】【POI2000】公共串


    后缀数组


      好感动,复习了下后缀数组居然写出来了……(感谢ykz大神)

      求最长公共子串……WA了一发是因为:【不同字符串之间要用不同的特殊字符隔开】否则就会匹配到相同→_→比如都是aaa结尾,如果用相同特殊字符就会使得最长公共子串变成aaa#这样子……

      1 /**************************************************************
      2     Problem: 2946
      3     User: Tunix
      4     Language: C++
      5     Result: Accepted
      6     Time:60 ms
      7     Memory:4104 kb
      8 ****************************************************************/
      9  
     10 //BZOJ 2946
     11 #include<vector>
     12 #include<cstdio>
     13 #include<cstring>
     14 #include<cstdlib>
     15 #include<iostream>
     16 #include<algorithm>
     17 #define rep(i,n) for(int i=0;i<n;++i)
     18 #define F(i,j,n) for(int i=j;i<=n;++i)
     19 #define D(i,j,n) for(int i=j;i>=n;--i)
     20 #define pb push_back
     21 using namespace std;
     22 typedef long long LL;
     23 inline int getint(){
     24     int r=1,v=0; char ch=getchar();
     25     for(;!isdigit(ch);ch=getchar()) if(ch=='-')r=-1;
     26     for(; isdigit(ch);ch=getchar()) v=v*10+ch-'0';
     27     return r*v;
     28 }
     29 const int N=1e5+10,INF=~0u>>2;
     30 /*******************template********************/
     31 int sa[N],rank[N],height[N],belong[N],wa[N],wb[N],c[N],n,m;
     32 int len[6];
     33 char s[N];
     34 bool cmp(int *r,int a,int b,int l){
     35     return r[a]==r[b] && r[a+l]==r[b+l];
     36 }
     37 void DA(char *s,int *sa,int n,int m){
     38     int i,j,p,*x=wa,*y=wb;
     39     rep(i,m) c[i]=0;
     40     rep(i,n) c[x[i]=s[i]]++;
     41     F(i,1,m-1) c[i]+=c[i-1];
     42     D(i,n-1,0) sa[--c[x[i]]]=i;
     43     for(j=1,p=0;p<n;j<<=1,m=p){
     44         for(p=0,i=n-j;i<n;i++) y[p++]=i;
     45         rep(i,n) if (sa[i]>=j) y[p++]=sa[i]-j;
     46  
     47         rep(i,m) c[i]=0;
     48         rep(i,n) c[x[y[i]]]++;
     49         F(i,1,m-1) c[i]+=c[i-1];
     50         D(i,n-1,0) sa[--c[x[y[i]]]]=y[i];
     51         swap(x,y); p=1; x[sa[0]]=0;
     52         F(i,1,n-1) x[sa[i]]=cmp(y,sa[i-1],sa[i],j) ? p-1 : p++;
     53     }
     54 }
     55 void calheight(char *s,int *sa,int n){
     56     int k=0;
     57     F(i,1,n) rank[sa[i]]=i;
     58     rep(i,n){
     59         if (k) k--;
     60         int j=sa[rank[i]-1];
     61         while(s[i+k]==s[j+k]) k++;
     62         height[rank[i]]=k;
     63     }
     64 }
     65 int main(){
     66 #ifndef ONLINE_JUDGE
     67     freopen("2946.in","r",stdin);
     68     freopen("2946.out","w",stdout);
     69 #endif
     70     n=getint();int l=0;
     71     F(i,1,n){
     72         scanf("%s",s+l);
     73         len[i]=strlen(s)-l;
     74         l=strlen(s);
     75         s[l++]='a'-n+i;
     76     }
     77     rep(i,l) s[i]=s[i]-'a'+10;
     78     l--;
     79     DA(s,sa,l+1,40);
     80     calheight(s,sa,l);
     81     int tmp=1;
     82     rep(i,l){
     83         if (s[i]<10) {tmp++;continue;}
     84         belong[rank[i]]=tmp;
     85     }
     86  
     87  
     88     bool vis[6]={0};
     89     int L=0,R=2000,mid,cnt,ans=0;
     90     while(L<=R){
     91         mid=(L+R)>>1;bool sign=0;
     92         cnt=0; memset(vis,0,sizeof vis);
     93         F(i,n,l){
     94             if (height[i]<mid){
     95                 cnt=1;memset(vis,0,sizeof vis);
     96                 vis[belong[i]]=1; continue;
     97             }
     98             if (!vis[belong[i]]) vis[belong[i]]=1,cnt++;
     99             if (cnt==n) sign=1;
    100         }
    101         if (sign) ans=mid,L=mid+1;
    102         else R=mid-1;
    103     }
    104     printf("%d
    ",ans);
    105     return 0;
    106 }
    View Code

    2946: [Poi2000]公共串

    Time Limit: 3 Sec  Memory Limit: 128 MB
    Submit: 160  Solved: 67
    [Submit][Status][Discuss]

    Description

     
           给出几个由小写字母构成的单词,求它们最长的公共子串的长度。
    任务:
    l        读入单词
    l        计算最长公共子串的长度
    l        输出结果
     

    Input

     
    文件的第一行是整数 n1<=n<=5,表示单词的数量。接下来n行每行一个单词,只由小写字母组成,单词的长度至少为1,最大为2000
     

    Output

    仅一行,一个整数,最长公共子串的长度。
     

    Sample Input

    3
    abcb
    bca
    acbc

    Sample Output

    HINT

    Source

    [Submit][Status][Discuss]
  • 相关阅读:
    背包问题
    floyed算法
    读Windows编程
    PB串口编程资料(转)
    读TCP-IP详解卷1:协议(1)
    Oracle把两个空格以上的空格,替换为两个空格
    PB中multieditline空间的“~r~n"转"~n"
    PB中掉用Run以后,等Run的程序关闭以后才会执行后边的语句
    一个关于生成随机数的算法
    英语词根
  • 原文地址:https://www.cnblogs.com/Tunix/p/4399355.html
Copyright © 2020-2023  润新知