hdu 1238 Substrings KMP问题



给出一些字符串,找出最大满足条件的连续子串使之满足:在每一个字符串中都正序存在或逆序存在。输出最大长度。

Substrings

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 8758    Accepted Submission(s): 4088


Problem 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 file 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
 

Author
Asia 2002, Tehran (Iran), Preliminary
 

Recommend
Eddy   |   We have carefully selected several similar problems for you:   1239  1240  1016  1242  1072 
 


我的做法是把第一个字符串当作缝衣针,其他字符串先翻转,与自身组成两人一组。

对于每一组求出缝衣针中每个位置能匹配的最大长度。

之后求出所有非缝衣针字符集合中 缝衣针字符串每个位置能匹配的最大长度。

取所有位置的最大值。

/**==========================================
 *   This is a solution for ACM/ICPC problem
 *
 *   @source:hdu 1238 Substrings
 *   @type:  data_structrue KMP
 *   @author: wust_ysk
 *   @blog:  http://blog.csdn.net/yskyskyer123
 *   @email: 2530094312@qq.com
 *===========================================*/
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int INF =0x3f3f3f3f;
const int maxn=100    ;
//const int maxV=12    ;
string N[2*maxn+5];
string M;
string S;
int  nex[maxn+5];
int len[2*maxn+5];
int len_S;
int len_M,n;

int dp[2*maxn][maxn+5];
void get(int ind)
{
    int p=ind-1;
    N[ind]="";
    for(int i=len[p]-1;i>=0;i--)
    {
        N[ind]+=N[p][i];
    }
}

void getnex()
{
    nex[0]=nex[1]=0;
    for(int i=1;i<len_M;i++)
    {
        int p=nex[i];
        while(p&&M[p]!=M[i])  p=nex[p];
        nex[i+1]= M[p]==M[i]? p+1:0;

    }
}


void KMP(int ind,int delta)
{
    int p=0;
    for(int i=0;i<len[ind];i++)
    {
        while(p&&M[p]!=N[ind][i])  p=nex[p];
        if(M[p]==N[ind][i])
        {
            dp[ind][delta+p]=max(dp[ind][delta+p],p+1 );
            p++;
        }
        if(p==len_M)  p=nex[p];
    }
}

void getmax(int ind)
{
    for(int i=0;i<len_S;i++)
    {
        dp[ind][i]=max(dp[ind][i],dp[ind+1][i]);
    }
}
void work()
{
    memset(dp,0,sizeof dp);
     for(int st=0;st<len_S;st++)
    {
        M=S.substr(st,len_S);
        len_M=len_S-st;
        getnex();
        for(int i=0;i<n;i++)
      {
        KMP( 2*i+1,st );
        KMP( 2*i+2,st );

      }
  }

  for(int i=0;i<n;i++)
  {
      getmax(2*i+1);
  }
  int ans=0;
  memset(dp[0],0x3f,sizeof dp[0]);


    for(int j=0;j<len_S;j++)
    {
        for(int i=1;i<=2*n-1;i+=2)
        {
             dp[0][j]=min(dp[0][j],dp[i][j]  );
        }
        ans=max(ans,dp[0][j]);

    }
    printf("%d\n",ans);





}
int main()
{
    int T;cin>>T;
    while(T--)
    {
        cin>>n;
        cin>>S;
        len_S=S.length();
        if(--n==0)  {printf("%d\n",len_S);continue;}
        for(int i=0;i<n;i++)
        {
            cin>>N[2*i+1];
            len[2*i+2]=len[2*i+1]=N[2*i+1].length();
            get(2*i+2);
        }
        work();


    }

   return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值