poj1226

题目链接:http://poj.org/problem?id=1226

题意:就是求n个字符串的最长公共子串,子串是可以反转的

思路:

先对字符串排个序,最短的在最前面。然后通过枚举(从长到短)每一个最短串的子串,看其或其反串是否是其他所有串的子串。

#include <stdio.h>
#include <string>
#include <iostream>
#include <cstdlib>
#include <algorithm>

#define N 101
using namespace std;
int P[N],P1[N];

bool Comp(string s1, string s2)
{
     return s1.length() < s2.length();
}
void get_nextval(string ptrn, int plen, int *nextval)
{
     int i = 0;
     int j = -1;
     nextval[0] = -1;
     while(i < plen-1)
     {
             if(j == -1 || ptrn[i] == ptrn[j])
             {
                      ++i;
                      ++j;
                      if( ptrn[i] != ptrn[j] )
                          nextval[i] = j;
                      else
                          nextval[i] = nextval[j];
                          
             }
             else
                 j = nextval[j];
     }
 }
 
 int kmp_search(string  src, int slen, string pat, int plen, int const* nextval, int pos)
 {
     int i = pos;
     int j = 0;
     while( i < slen && j < plen)
     {
            if( j == -1 || src[i] == pat[j] )
            {
                ++i;
                ++j;    
            }       
            else
            {
                j = nextval[j];    
            }
     }    
     if( j >= plen )
         return i-plen;
     else
         return -1;
 }
 
 int main(int argc, char** argv)
 {
     int t,m,n;
     string s[101];
     cin>>t;
     while(t--)
     {
         int h;
         cin>>h;
         for(int i=0; i<h; i++)
             cin>>s[i];
         sort(s, s+h, Comp);
         string a,b;
         int len = s[0].length();
         int flag = 0;
         
         for(int i = len; i>0; i--)
         {
                 for(int j=0; j<=len-i; j++)
                 {
                         a = s[0].substr(j, i);
//                         cout<<"a=" <<a<<endl;
                         b = a;
                         reverse(b.begin(), b.end());
                         m = a.length();
                         int k;
                         for(k=1; k<h; k++)
                         {
                              n = s[k].length();
//                              cout<<"s[k]="<<k<<"   "<<s[k]<<endl;
                              get_nextval(a, m, P);
                              get_nextval(b, m, P1);
//                              int kmp1 = kmp_search(s[k], n, a, m, P, 0);
//                              cout<<kmp1<<endl;
//                              int kmp2 = kmp_search(s[k], n, b, m, P1, 0);
//                              cout<<kmp2<<endl;
                              if( (kmp_search(s[k], n, a, m, P, 0) == -1) && (kmp_search(s[k], n, b, m, P1, 0) == -1) )
                                  break;       
                         }    
                         
                         if(k == h)
                         {
                              flag = 1;
                              break;     
                         }    
                 }
                 if(flag)break;
         }      
         
         if(flag)
                 cout<<a.length()<<endl;
         else
                 cout<<0<<endl;
     }    
     return 0;
 }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值