感受
思
路
很
简
单
,
就
是
不
知
道
k
m
p
还
可
以
求
最
小
循
环
节
长
度
思路很简单,就是不知道kmp还可以求最小循环节长度
思路很简单,就是不知道kmp还可以求最小循环节长度
思路
显
然
,
我
们
需
要
枚
举
p
即
后
缀
n
、
后
缀
n
−
1
、
.
.
.
显然,我们需要枚举p即后缀n、后缀n-1、...
显然,我们需要枚举p即后缀n、后缀n−1、...
对
于
每
一
个
后
缀
,
我
们
需
要
找
到
最
小
的
l
即
最
小
循
环
节
长
度
对于每一个后缀,我们需要找到最小的l即最小循环节长度
对于每一个后缀,我们需要找到最小的l即最小循环节长度
通
过
这
样
,
可
以
最
大
化
a
∗
p
−
b
∗
l
通过这样,可以最大化a*p-b*l
通过这样,可以最大化a∗p−b∗l
问
题
转
化
:
如
何
求
出
一
个
串
的
最
小
循
环
节
长
度
?
问题转化:如何求出一个串的最小循环节长度?
问题转化:如何求出一个串的最小循环节长度?
a
n
s
=
串
长
度
−
串
前
缀
与
后
缀
的
最
长
公
共
部
分
(
n
e
x
t
数
组
)
ans=串长度-串前缀与后缀的最长公共部分(next数组)
ans=串长度−串前缀与后缀的最长公共部分(next数组)
结
论
不
太
会
证
明
,
直
接
记
住
应
该
也
可
。
结论不太会证明,直接记住应该也可。
结论不太会证明,直接记住应该也可。
#include <bits/stdc++.h>
#define next NEXT
using namespace std;
typedef long long ll;
const int maxn = 1e7 + 10;
int next[maxn], n, m;
char s[maxn], t[maxn];
ll a, b;
void initkmp(char x[], int m){
int i = 0, j = next[0] = -1;
while(i < m){
while(j != -1 && x[i] != x[j]) j = next[j];
next[++i] = ++j;
}
}
int main(){
scanf("%lld%lld", &a, &b);
scanf("%s", s + 1);
n = strlen(s + 1);
for(int i = n; i >= 1; i--){
if(s[i] == '.') break;
t[m++] = s[i];
}
initkmp(t, m);
bool ok = false; ll ans;
for(int i = 1; i <= m; i++){
if(!ok) ans = a * i - b * (i - next[i]), ok = true;
else ans = max(ans, a * i - b * (i - next[i]));
}
printf("%lld\n", ans);
return 0;
}