标签:
2 annivddfdersewwefary nniversarya
题意,就是给一段字符串,要求找出目标串,且最多只能三个片段串。
由于s很小,所以用深搜,暴力乱搞就好了。但这里用dp也能解决。复杂度是o(n)
定义pre[i][j] 表示字符串第i个位置,从目标串往后能匹配pre[i][j] 个,也就是说s(i,i+pre[i][j] ) == g(j,j+pre[i][j] ) g表示目标串。
则pre[i][j] 转状转移很简单就是pre[i+1][j+1]转移来就可以了。
定义dp[i][j]表示,字符串第i-1个位置前已经匹配到了目标串g的第j-1个位置且已用的分段数就是dp[i][j]。则状态转移方程就是
dp[i][j]可以从dp[i-1][j]得来,也可以转移到dp[i+pre[i][j]][j+pre[i][j]],取分段数的最小值。
答案只要dp[s][11]大于1,说明存在。
由于本题目标串g的长度为定值,所以复杂度为o(s * 11)线性算法,如果,改变一下,g不是字长,而是变长的,那么复杂度则为o(s* g)了,与分段数是无关的。
#define N 205
#define M 100005
#define maxn 205
#define MOD 1000000000000000007
int n,glen,len,dp[N][12],pre[N][11];
char str[N];
char goal[20] = "anniversary";
void Update(int & a,int b){
    if(a == 0) a = b;
    else a = min(a,b);
}
int main()
{
    glen = strlen(goal);
    while(S(n)!=EOF)
    {
        while(n--){
            SS(str);len = strlen(str);
            FI(len){
                FJ(11){
                    if(str[i] == goal[j]) pre[i][j] = 1;
                    else pre[i][j] = 0;
                }
            }
            for(int i = len - 2;i>=0;i--){
                FJ(10){
                    if(pre[i][j] && pre[i+1][j+1]) pre[i][j] = pre[i+1][j+1] + 1;
                }
            }
            fill(dp,0);
            for(int i = 0;i<len;i++){
                FJ(11){
                    if(i && dp[i-1][j])   Update(dp[i][j],dp[i-1][j]);
                    if((dp[i][j] || !j )&&dp[i][j] < 3 && pre[i][j]){
                     Update(dp[i+pre[i][j]][j+pre[i][j]],dp[i][j] + 1);
                    }
                }
            }
            bool flag = true;
            for(int i = 0;i<=len && flag;i++){
                if(dp[i][11]) flag = false;
            }
            if(!flag)
                printf("YES\n");
            else
                printf("NO\n");
        }
    }
    return 0;
}#define N 205
#define M 100005
#define maxn 205
#define MOD 1000000000000000007
int n,glen,len;
char str[N];
char goal[20] = "anniversary";
bool DFS(int si,int gi,int num){
    if(num <=3 && gi >= glen) return true;
    if(num > 3) return false;
    for(int i = si;i<len;i++){
        int ti = i,tgi = gi;
        while(ti<len && tgi < glen && str[ti] == goal[tgi]) tgi++,ti++;
        if(ti > i && DFS(ti,tgi,num + 1)) return true;
    }
    return false;
}
int main()
{
    glen = strlen(goal);
    while(S(n)!=EOF)
    {
        while(n--){
            SS(str);len = strlen(str);
            if(DFS(0,0,0))
            printf("YES\n");
            else
            printf("NO\n");
        }
    }
    return 0;
}YES NO
版权声明:本文为博主原创文章,未经博主允许不得转载。
hdu 5311 Hidden String dp o(n)算法 深搜
标签:
原文地址:http://blog.csdn.net/mengzhengnan/article/details/47082301