POJ 1226 Substrings(最长公共连续串的变形,可以倒转+KMP)

Substrings
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 10451   Accepted: 3598

Description

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 

                 题目大意:给你n个串,求最小公共连续子串,不过这个可以倒转,比如ro和or可以匹配

         解题思路:思路很清晰,把第一个串当模式串,分解求next匹配然后逆转求next匹配。自己的思路是先顺序找到子串,然后再找它的逆转串的相对位置。例如模式串abcdefg,我先逆转模式串放在另一个数组里面。子串可以是bcde(sta=1,len=1+4)逆转就变成了edcb(sta=7-1-4,len=7-1).这样把规律看出来就可以了。果断一A!

         题目地址:Substrings

AC代码:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
using namespace std;
int nextp[105],nexts[105],n;
char a[105][105];
char b[105];  //将模式串翻转
int lena0; //模式串的长度
//我的思路是用第一个字符串当模式串,然后再枚举长度由大到小求next匹配

void getnextp(int sta,int len)   //模式串
{
     int i,j;
     len=sta+len;   //相对位置变成绝对位置
     nextp[sta]=sta,nextp[sta+1]=sta;
     for(i=sta+1;i<len;i++)
     {
          j=nextp[i];
          while(j!=sta&&a[0][i]!=a[0][j])
               j=nextp[j];
          if(a[0][i]==a[0][j])
               nextp[i+1]=j+1;
            else
               nextp[i+1]=sta;
     }
}

void getnexts(int sta,int len)   //翻转后的模式串
{
     int i,j;
     sta=lena0-sta-len;    //要把子串的位置转换成b的位置
     len=sta+len;
     nexts[sta]=sta,nexts[sta+1]=sta;
     for(i=sta+1;i<len;i++)
     {
          j=nexts[i];
          while(j!=sta&&b[i]!=b[j])
               j=nexts[j];
          if(b[i]==b[j])
               nexts[i+1]=j+1;
            else
               nexts[i+1]=sta;
     }
}

int KMP(int sta,int len)
{
     int i,j,k;
     int sta1=sta;
     int sta2=lena0-sta-len;
     int len1=sta+len;  
     int len2=sta2+len;
     for(k=1;k<n;k++)   //后面的串都和第一个串的子串匹配
     {
          int flag=0;
          j=sta1;
          for(i=0;i<strlen(a[k]);i++)
          {
               while(j!=sta1&&a[k][i]!=a[0][j])
                    j=nextp[j];
               if(a[k][i]==a[0][j])
                    j++;
               if(j==len1)
               {
                  flag=1;
                  break;
               }
          }

          j=sta2;
          for(i=0;i<strlen(a[k]);i++)
          {
               while(j!=sta2&&a[k][i]!=b[j])
                    j=nexts[j];
               if(a[k][i]==b[j])
                    j++;
               if(j==len2)
               {
                  flag=1;
                  break;
               }
          }
          if(flag==0)    //有一个没有匹配,便返回0
               return 0;
     }
     return 1;
}


int main()
{
     int i,j,T,l;
     scanf("%d",&T);
     while(T--)
     {
          scanf("%d",&n);
          if(n==0)
             break;
          for(i=0;i<n;i++)
               scanf("%s",a[i]);
          lena0=strlen(a[0]);
          for(i=0;i<lena0;i++)
               b[i]=a[0][lena0-i-1];
          b[lena0]='\0';
          int flag=0;
          for(i=lena0;i>=1;i--)  //从长度lena0开始往下枚举
          {
             int flag1=0;    //长度为i的是否存在
             for(j=0;j<=lena0-i;j++)  //模式串分解的起始位置
             {
                 getnextp(j,i);
                 getnexts(j,i);
                 if(KMP(j,i))
                 {
                     flag1=1;
                     printf("%d\n",i);
                     break;
                 }
             }
             if(flag1)
             {
                  flag=1;
                  break;
             }
          }
          if(flag==0)
            puts("0");
     }

     return 0;
}



你可能感兴趣的:(KMP,poj,最长公共连续子串变形)