【考前模拟】加密 (正解:容斥原理或暴力)
加密
【问题描述】
有一种不讲道理的加密方法是: 在字符串的任意位置随机插入字符。 相应的,
不讲道理的解密方法就是从字符串中恰好删去随机插入的那些字符。
给定原文?和加密后的字符串?,求?有多少子串可以通过解密得到原文?。
【输入格式】
输入第一行包含一个字符串?,第二行包含一个字符串?。
【输出格式】
输出一行,包含一个整数,代表可以通过解密得到原文的?的子串的数量。
【样例输入】
abcabcabc
cba
【样例输出】
9
【样例解释】
用[?,?]表示子串开头结尾的下标(从 0 开始编号) ,这 9 种方案是:
[0,6],[0,7],[0,8],[1,6],[1,7],[1,8],[2,6],[2,7],[2,8]
【数据规模和约定】
30%的数据,|?| 1000。
对于100%的数据,1 ≤ |?| ≤ 300,000,1 ≤ ? ≤ 200。
思路:
超时代码(待修改):
#include<iostream> #include<cstdio> #include<cstring> using namespace std; char T[1000010],S[210]; int kszb[1000010]; long long int J=1,ha,te,t,ans; bool ok; int add(int ha_now,int te_now,int ha_last) { return (ha_now-ha_last-1)*(strlen(T)-(te_now))+(strlen(T)-(te_now)); } int minuss(int length_now,int length_S){ if(length_now==length_S) return -1; else return 0; } int main(){ freopen("encrypt.in","r",stdin); freopen("encrypt.out","w",stdout); cin>>T; cin>>S; kszb[0]=-1; for(int i=0;i<strlen(T);i++) { if(T[i]==S[0]) kszb[J++]=i; } for(int i=1;i<J;i++) { ha=te=kszb[i],t=0,ok=0; while(1) { if(t==strlen(S)){ t=0; te--; break; } if(te==strlen(T)){ ok=1; break; } if(T[te]==S[t]){ te++; t++; } else te++; } if(!ok) { ans+=add(ha,te,kszb[i-1]); ans+=minuss(te-ha+1,strlen(S)-1); } else break; } cout<<ans; fclose(stdin); fclose(stdout); }
这是没超时的代码:
#include<iostream> #include<cstring> #include<cstdio> #ifdef WIN32 #define lll "%I64d" #else #define lll "%lld" #endif using namespace std; char t[300010],s[210]; int l,r,lent,lens,ok; long long ans; int sq[300010],thead,ttail; int front(int b,int ll,int rr) { return (ll-b-1)*(lent-rr); } int behind(int rr) { return lent-rr; } void pan(int ll,int rr) { if((rr-ll+1)==lens) ans--; } void find(int &th,int &tt) { int st=0; while(1) { if(st==lens) { tt--; st=0; break; } if(tt==lent) { ok=1; break; } if(t[tt]==s[st]) { tt++; st++; } else tt++; } } int main() { freopen("encrypt.in","r",stdin); freopen("encrypt.out","w",stdout); cin>>t>>s; lent=strlen(t);lens=strlen(s); for(int i=0;i<lent;i++) if(t[i]==s[0]) sq[++sq[0]]=i; int z=sq[0];sq[0]=-1; for(int i=1;i<=z;i++) { ok=0; thead=sq[i];ttail=sq[i]; find(thead,ttail); if(!ok) { ans=ans+1ll*front(sq[i-1],thead,ttail); ans=ans+1ll*behind(ttail); pan(thead,ttail); } else break; } printf(lll,ans); fclose(stdin); fclose(stdout); return 0; }
请各位同志找找不同;
细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。
雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。