poj3080(串-KMP+枚举)

 题意:有2到10个case,每个case里有n个长度都为60的串,求出它们的最长公共子串,如果这个子串的长度 < 3则输出“no significant commonalities”,如果存在多个最长公共子串,则输出字典序最小的那一个。

 

思路,KMP+枚举,从第0个串中,从长度为60开始,不断选取子串,与其他串做比较,假如在某长度发现了都匹配,压入结果,将同长度的子串按字典序排序,输出最小

 

  
  
  
  
  1. #include<iostream> 
  2. #include<string> 
  3. #include<vector>  
  4. #define MAXSIZE 60 //输入比较的字符串长度  
  5. using namespace std; 
  6.  
  7. void get_nextval(string T,int *nextval) 
  8.    int i,j; 
  9.    i = 1; 
  10.    j = 0; 
  11.    nextval[1] = 0;  //经常忘掉这一句  
  12.    while(i<T.size()-1) 
  13.    { 
  14.       if(j==0||T[i]==T[j]) 
  15.       { 
  16.          ++i; 
  17.          ++j; 
  18.          if(T[i]!=T[j]) 
  19.          { 
  20.             nextval[i] = j; 
  21.          } 
  22.          else 
  23.          { 
  24.             nextval[i] = nextval[j]; 
  25.          } 
  26.       } 
  27.       else 
  28.       { 
  29.          j = nextval[j]; 
  30.       } 
  31.    } 
  32. }  
  33.  
  34. int Index_KMP(string S,string T,int pos) 
  35.    int i = pos; 
  36.    int j = 1; 
  37.    int nextval[255]; 
  38.    get_nextval(T,nextval); 
  39.    while(i<=S.size()-1&&j<=T.size()-1) 
  40.    { 
  41.       if(j==0||S[i] == T[j]) 
  42.       { 
  43.          i++; 
  44.          j++; 
  45.       } 
  46.       else 
  47.       { 
  48.          j = nextval[j]; 
  49.       } 
  50.    } 
  51.    if(j>T.size()-1) 
  52.       return i - T.size()+1; 
  53.    else 
  54.       return 0; 
  55.  
  56. int main() 
  57.    int cas,n; 
  58.    string head = "#";  
  59.    cin>>cas; 
  60.    vector<string> dna; 
  61.    vector<string> result; 
  62.    for(int i=0;i<cas;i++) 
  63.    { 
  64.       vector<string> dna; 
  65.       cin>>n; 
  66.       for(int j=0;j<n;j++) 
  67.       { 
  68.          string tmp; 
  69.          cin>>tmp; 
  70.          dna.push_back(head+tmp); 
  71.       } 
  72.       vector<string> result; 
  73.       for(int j=MAXSIZE;j>=3;j--)   //j表示要从第一个串里取出子串的长度  
  74.       { 
  75.           
  76.          for(int s = 1;s<MAXSIZE+2-j;s++) //s表示从第一个串里的第几个字符开始取这个子串  
  77.          { 
  78.             int flag2 = 1; 
  79.             string current = dna[0].substr(s,j); 
  80.             for(int l=1;l<dna.size();l++)   //对剩下的各个字符串进行子串匹配  
  81.             { 
  82.               flag2 = Index_KMP(dna[l],head+current,1); //注意,第一个参数是主串,第二个参数是子串  
  83.                
  84.                if(flag2==0)                          //假如碰到一个,不是其子串,直接break掉  
  85.                   break
  86.             } 
  87.             if(flag2>0)                              //把所有其他字符串都比较过后,发现都是子串,把此结果压到 结果向量中  
  88.                result.push_back(current); 
  89.         } 
  90.         if(result.size()>0)    //把同一个长度比完之后,假如已经有答案了,没必要去比较更小的子串,中断  
  91.            break
  92.      } 
  93.      if(result.size()==0) 
  94.         cout<<"no significant commonalities"<<endl; 
  95.      else 
  96.      { 
  97.         string small = result[0]; 
  98.         for(int j=1;j<result.size();j++) 
  99.         { 
  100.            if(result[j]<small) 
  101.               small = result[j]; 
  102.         } 
  103.         cout<<small<<endl; 
  104.      } 
  105.    } 
  106.    system("pause"); 
  107.     

你可能感兴趣的:(ACM题库)