hdu5510 Bazinga(KMP 剪枝) !!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_43408238/article/details/102701406

题意:给你一系列字符串,编号为1 - n ,然后让你找一个下标最大的串,在它之前存在一个串不是这个串的子串,如果有则输出这个串的 下标,如果没有则 输出 - 1。

思路:

KMP匹配。一看数据都挺小,直接匹配,结果TTTTTT............到这时,我仍旧没有什么好的想法,就看了看别人的题解,发现别人只是比我多了一个小小的剪枝,就跑的贼快。

多设一个vis数组,标记已经匹配成功的较小串,比如 1: avf  2:avfe   1与2 匹配成功,1是2的子串,所以下次匹配时就不需要在匹配1了,因为如果2匹配成功,1必然也能匹配成功。

所以只需要从小到大枚举就行了。

论剪枝的重要性!!!

AC Code:

#include<iostream>
#include<cstring>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<cmath>
#include<cstdio>
#include<iomanip>
#include<sstream>
#include<algorithm>

using namespace std;
#define read(x) scanf("%d",&x)
#define Read(x,y) scanf("%d%d",&x,&y)
#define sRead(x,y,z)  scanf("%d%d%d",&x,&y,&z)
#define gc(x)  scanf(" %c",&x);
#define mmt(x,y)  memset(x,y,sizeof x)
#define write(x) printf("%d\n",x)
#define INF 0x3f3f3f3f
#define ll long long
#define mod  998244353
#define pdd pair<double,double>
const int N = 1000;
const int M=  1e6+5;
int Next[501][2001];
char s[501][2001];
bool vis[2001];
void kmp_pre(int id){
    int i = 0,j = Next[id][0] = -1;
    int m = strlen(s[id]);
    while(i < m){
        while(j != -1 &&s[id][i] != s[id][j]) j = Next[id][j];
        if(s[id][++i] == s[id][++j]) Next[id][i] = Next[id][j];
        else Next[id][i] = j;

    }
}
bool kmp(int id1,int id2){
    int i = 0,j = 0;
    int n = strlen(s[id2]);
    int m = strlen(s[id1]);
    while(i < n){
        while(j!=-1&&s[id2][i] != s[id1][j]) j = Next[id1][j];
        ++i,++j;
        if(j >= m) return 1;
    }
    return 0;
}
int main()
{
    int T;
    read(T);
    for(int p = 1;p <= T;++p){
        mmt(vis,0);
        int n;
        read(n);
        for(int i = 1;i <= n;++i)  scanf("%s",s[i]),kmp_pre(i);
            int k = -1;
            bool r = 1;
           for(int i = 2;i <= n;++i){
            for(int j = 1;j < i;++j){
                if(vis[j]) continue;//剪枝
                if(kmp(j,i)) vis[j] = 1;
                else k = i;
            }
           }
        printf("Case #%d: %d\n",p,k);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_43408238/article/details/102701406