JZOJ 3669【HNOI2014】抄卡组

来源:互联网 发布:软件编程是什么 编辑:程序博客网 时间:2024/05/23 02:03

Description:

这里写图片描述

Input:

这里写图片描述

Output:

这里写图片描述

Sample Input:

3
3
wellplayed
thankyou
pyroblast
2
a*abc
abc*a
2
a*abc
a1234567890abc

Sample Output:

N
N
Y

Data Constraint:

这里写图片描述

题目大意:

字符串中,*可以替代成任何长度任何模样的字符串,给出T组,每组n个字符串,求两两之间是否能匹配。

题解:

如果n个字符串都带星号,只需要判断字符串的第一个星号之前的字符串是否完全相同,最后一个星号的字符串是否完全相同。
如果有一个不带星号的字符串,用它去和其它的匹配,假设它是A串,待匹配的串是B串,只需要判断星号之间的字符串是否按顺序地出现在A串,用KMP解决即可。

Code:

#include<cstdio>#include<cstring>#include<algorithm>#define fo(i, x, y) for(int i = x; i <= y; i ++)#define fd(i, x, y) for(int i = x; i >= y; i --)#define min(a, b) ((a) < (b) ? (a) : (b))#define max(a, b) ((a) > (b) ? (a) : (b))using namespace std;const int Maxc = 20000005, Maxn = 100005;int T, n, l[Maxn], r[Maxn], p[Maxn];int next[Maxc];char c[Maxc];bool pd(int x, int y) {    if(!p[x] && !p[y]) {        if(r[x] - l[x] != r[y] - l[y]) return 0;        fo(i, 0, r[x] - l[x]) if(c[l[x] + i] != c[l[y] + i]) return 0;        return 1;    }    if(!p[x]) swap(x, y);    int u = 0, v = 0;    fo(i, l[x], r[x]) {if(c[i] == '*') break; u ++;}    fd(i, r[x], l[x]) {if(c[i] == '*') break; v ++;}    if(!p[y] && u + v > r[y] - l[y] + 1) return 0;    fo(i, 0, u - 1) {        if(c[l[y] + i] == '*') break;        if(c[l[y] + i] != c[l[x] + i]) return 0;    }    fo(i, 0, v - 1) {        if(c[r[y] - i] == '*') break;        if(c[r[y] - i] != c[r[x] - i]) return 0;    }    return 1;}void Get_next(int x, int y) {    next[x] = 0;    int i = 0;    fo(j, x + 1, y) {        while(i > 0 && c[x + i] != c[j]) i = next[x + i - 1];        if(c[x + i] == c[j]) i ++;        next[j] = i;    }}void Work() {    int ans = 1, bz = 0;    scanf("%d", &n);    fo(i, 1, n) {        l[i] = r[i - 1] + 1; r[i] = r[i - 1];        char ch = ' '; for(;! ((ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '*'); ch = getchar());        for(; (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '*'; ch = getchar())            c[++ r[i]] = ch;        p[i] = 0;        fo(j, l[i], r[i]) if(c[j] == '*') p[i] = 1;        if(!p[i]) bz = 1;    }    if(bz == 0) {        fo(i, 1, n) {            fo(j, i + 1, n) if(!pd(i, j)) {                ans = 0; break;            }            if(ans == 0) break;        }        if(ans) printf("Y\n"); else printf("N\n");        return;    }    fo(k, 1, n) if(!p[k]) bz = k;    fo(k, 1, n) if(k != bz) {        if(!pd(bz, k)) {            ans = 0; break;        }        if(!p[k]) continue;        int st = l[bz], en = r[bz], st2 = l[k], en2 = r[k];        fo(i, l[k], r[k]) {            if(c[i] == '*') break;            st ++; st2 ++;        }        fd(i, r[k], l[k]) {            if(c[i] == '*') break;            en --; en2 --;        }        while(st2 < en2) {            st2 ++;            fo(d, st2, en2) {                if(c[d] == '*') {                    if(st2 == d) break;                    Get_next(st2, d - 1);                    int i = 0, bz = 0;                    fo(j, st, en) {                        while(i && c[st2 + i] != c[j]) i = next[st2 + i - 1];                        if(c[st2 + i] == c[j]) i ++;                        if(i == d - st2) {                            bz = 1;                            st = j + 1;                            st2 = d;                            break;                        }                    }                    if(!bz) ans = 0;                     break;                }            }            if(ans == 0) break;        }        if(ans == 0) break;    }    if(ans) printf("Y\n"); else printf("N\n");}int main() {     freopen("hs.in", "r", stdin);    freopen("hs.out", "w", stdout);    for(scanf("%d", &T); T; T --)        Work();}
原创粉丝点击