【JZOJ6379】【NOIP2019模拟2019.10.06】小w与密码(password)
题目大意
给出两个串S,TS,T,你可以通过拼接SS的某个前缀和TT的某个前缀得到一个新串(SS的前缀在前),求能得到多少种不同的新串。
Solution
若一个串出现了多次,设它可以被表示成s+ts+t或s′+t′。我们令t′比t更长,显然t是t′的一个border。尽管t′有多个border,但实际上只用减去最长的border带来的影响,因为更短的border已经在这个长border计算过了。考虑把t从t′的后面去掉,剩下的t′的一个前缀,若它在S中作为一个子串且不作为前缀出现,它就会被重复计算,减掉该前缀在S中出现次数即可。求前缀出现次数只需要将T和S匹配并用next数组做一次后缀和。
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100007;
long long ans;
int lens, lent, next[N], num[N];
char s[N], t[N];
int main() {
freopen("password.in", "r", stdin);
freopen("password.out", "w", stdout);
scanf("%s%s", s + 1, t + 1);
lens = strlen(s + 1);
lent = strlen(t + 1);
ans = 1ll * lens * lent;
for (int i = 2, j = 0; i <= lent; ++i) {
while (j && t[j + 1] != t[i]) j = next[j];
if (t[j + 1] == t[i]) ++j;
next[i] = j;
}
for (int i = 2, j = 0; i <= lens; ++i) {
while (j && t[j + 1] != s[i]) j = next[j];
if (t[j + 1] == s[i]) ++j;
++num[j];
}
for (int i = lent; i >= 2; --i) num[next[i]] += num[i];
for (int i = 2; i <= lent; ++i) if (next[i]) ans -= num[i - next[i]];
printf("%lld\n", ans);
return 0;
}
作者:zjlcnblogs
出处:https://www.cnblogs.com/zjlcnblogs/p/11627811.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
分类:
OI
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· ASP.NET Core 模型验证消息的本地化新姿势
· 对象命名为何需要避免'-er'和'-or'后缀
· SQL Server如何跟踪自动统计信息更新?
· AI与.NET技术实操系列:使用Catalyst进行自然语言处理
· 分享一个我遇到过的“量子力学”级别的BUG。
· dotnet 源代码生成器分析器入门
· 官方的 MCP C# SDK:csharp-sdk
· 从零开始:基于 PyTorch 的图像分类模型
· [WPF] 在RichTextBox中输出Microsoft.Extension.Logging库的
· 一步一步教你部署ktransformers,大内存单显卡用上Deepseek-R1