QDUOJ 蒸鱼的一个简单签到题 思维+kmp

来源:互联网 发布:idea修改js不重启 编辑:程序博客网 时间:2024/06/10 08:11

传送门:QDUOJ

思路:其实比赛时想的思路就和正解差不多了,但是感觉会T就没敢写。。

正解:由蒸鱼字符串定义以及字符串匹配性质可知:

1.如果前一个字符串不是蒸鱼字符串,并且当前字符串能和前一个匹配,那么当前字符串也不是蒸鱼字符串,如果当前字符串不能和前一个匹配,那么当前字符串就一定是蒸鱼字符串。

2.如果前一个是蒸鱼字符串,那么当前这个字符串就要往前匹配,但并不需要全部匹配,只需要匹配前面的蒸鱼字符串,和一组连续非蒸鱼字符串的最后一个就行了。并且这个向前匹配的过程中匹配成功的字符串都可以删掉了(以后不再进行匹配),一但出现匹配失败,则说明当前字符串为蒸鱼字符串。这个过程可以用一个栈完美的处理。

代码:

#include<bits/stdc++.h>#define ll long long#define pb push_back#define fi first#define se second#define pi acos(-1)#define inf 0x3f3f3f3f#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1#define rep(i,x,n) for(int i=x;i<n;i++)#define per(i,n,x) for(int i=n;i>=x;i--)using namespace std;#define next nxttypedef pair<int,int>P;const int MAXN=100010;int gcd(int a,int b){return b?gcd(b,a%b):a;}void kmp_pre(char x[],int m,int next[]){int i=0,j;j=next[0]=-1;while(i<m){while(-1!=j&&x[i]!=x[j]) j=next[j];next[++i]=++j;}}int next[10010];int kmp_count(char x[],int m,char y[],int n)//x是模式串,y是主串 {int i,j,ans=0;kmp_pre(x,m,next);i=j=0;while(i<n){while(-1!=j&&y[i]!=x[j]) j=next[j];i++,j++;if(j>=m){ans++;j=next[j];}}return ans;}char s[1010][2010];int len[1010];vector<int>ans;stack<int>q;int main(){int T,n;cin>>T;while(T--){ans.clear();while(!q.empty())q.pop();scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%s",s[i]);len[i]=strlen(s[i]);}for(int i=1;i<=n;i++){while(!q.empty()&&kmp_count(s[q.top()],len[q.top()],s[i],len[i])) q.pop();if(q.size()){q.push(i);ans.push_back(i);}elseq.push(i);}if(ans.empty()){puts("-1");}else{int sz=ans.size();printf("%d\n",sz);for(int i=0;i<sz;i++)printf("%d%c",ans[i]," \n"[i==sz-1]);}} return 0;}



原创粉丝点击