Codeforces Beta Round #71 C【KMP+DP】

Codeforces79C

题意:
求s串的最大子串不包含任意b串;

思路:

dp[i]为以i为起点的子串的最长延长距离。

我们可以想到一种情况就是这个 i 是某个子串的起点,子串的长度-1就是最短,

或者这个 前面的长度 +这个i 就是答案。
所以预处理一下,以 i 为起点的最短子串距离就好了,这里利用KMP比较方便。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

const int INF=0x3f3f3f3f;

const int N=1e5+10;
int vis[N];
char s[N];
int Next[N],lens,lenp;
int dp[N];	//dp[i]为以i为起点的最长距离。

void GetNext(char *str)
{
    int i=0,j=-1;  
    int len=strlen(str);
    Next[0]=-1;
    while(i<len)
    {
        if(j==-1||str[i]==str[j])  
            Next[++i]=++j;  
        else  
            j=Next[j];  
    }
}  

void KMP(char *p,int x)
{
	int i=0,j=0;
	lenp=strlen(p);
    while(i<lens&&j<lenp)  
    {
        if(j==-1||p[j]==s[i])  
        {
            i++;j++;  
        }  
        else
            j=Next[j];
        if(j==lenp)
        {
        	vis[i-lenp]=min(vis[i-lenp],lenp);
            j=Next[j];
        }
    }
}

int main()
{
	int n;
	char b[15];
	scanf("%s",s);
	lens=strlen(s);
	scanf("%d",&n);
	memset(vis,INF,sizeof(vis));
	
	for(int i=1;i<=n;i++)
	{
		scanf("%s",b);
		GetNext(b);
		KMP(b,i);
	}
	/*
	for(int i=0;i<lens;i++)
		printf("%d\n",vis[i]);
	puts(""); 
	*/
	int pos=lens;
	dp[n]=0;
	for(int i=lens-1;i>=0;i--)
	{
		dp[i]=min(vis[i]-1,dp[i+1]+1);
		if(dp[i]>dp[pos]) pos=i;
	}
	
	if(pos==lens)
	{
		puts("0 0");
		return 0;
	}
	printf("%d %d\n",dp[pos],pos);
	return 0;
}



posted @ 2017-03-16 21:27  see_you_later  阅读(129)  评论(0编辑  收藏  举报