CF176B Word Cut
CF176B Word Cut
挺厉害的一道题,做一些补充说明。
果然还是数数题不是很行。
首先可以观察到一点,对于一个字符,他在任何位置,他转一圈回来所得到的字符串是不会变化的,因为相对的顺序并没有改变。(其实可以手玩出来。)
所以就可以得到,这做了 次操作,就相当于只做了一次操作。(也就是最后一次)。
所以现在要解决,在 所有和 构成循环同构的字符串中,找到和 相等的字符串,把 复制一次跑字符串匹配即可,设符合的位置有 个。
因为对于一个字符,在哪个位置操作对构成的字符串都没有影响。所以不妨在 上操作,因为这样可以避免掉 的第一个字符不能转的问题。且处理来的 个位置,在 中同样符合转一次,和 重合的条件。
然后就设 表示转了 次,和 一样的种类,以及转出来其他串的情况。
转移就是:
在这里主要是注意一下不能从开头来转(因为没有位置可以断了),所以要减去 ,不然就是不操作,那就不合法了。
#include<bits/stdc++.h>
using namespace std;
const int N =1e6+10;
const int mod=1e9+7;
#define int long long
int k,f[N],dp[N][2],cnt,n;
char s[N],t[N];
void init(){
f[0]=-1;
int i=1,j=-1;
while(i<=n){
while(j!=-1&&t[i]!=t[j+1]) j=f[j];
f[i++]=++j;
}
}
void KMP(){
int j=0;
for(int i=1;i<=strlen(s+1);i++){
while(j!=-1&&t[j+1]!=s[i]) j=f[j];
j++;
if(j==n&&i-n+1<=n) cnt++;
}
}
signed main(){
scanf("%s%s%d",s+1,t+1,&k);
string a=s+1,b=t+1;
if(a==b) dp[0][0]=1;
else dp[0][1]=1;
n=strlen(s+1);
for(int i=1;i<=n;i++) s[i+n]=s[i];
init(),KMP();
for(int i=1;i<=k;i++){
dp[i][0]+=(dp[i-1][0]%mod*(cnt-1)%mod+dp[i-1][1]%mod*cnt%mod)%mod;
dp[i][1]+=((dp[i-1][0]%mod*(n-cnt)%mod)+(dp[i-1][1]%mod*(n-cnt-1)%mod))%mod;
dp[i][0]%=mod,dp[i][1]%=mod;
}
cout<<dp[k][0]<<endl;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现