题目大意
定义斐波那契字符串:
F(n)=⎧⎩⎨⎪⎪01F(i−1)+∗F(i−2)(n=0)(n=1)(n≥2)
*此处的+为字符串加法
求一个01串在
F(n) 中出现的次数
解答
将这个字符串在 F(i) 中出现的次数记为 G(i)
则不难发现: G(i)=G(i−1)+G(i−2)+该串在F(i−1)与F(i−2)交界处出现的次数
如果我们把最短的两个比这个01串长的斐波那契字符串记作 a,b
则 F(i−1)与F(i−2) 交界处无非是 a+b和b+a 两种情况而已,因为这两个串不是在 F(i) 的最前面就是在最后面
所以我们只要用KMP找到 a,b,a+b,b+a 中这个串出现的次数,就可以递归求出 G(n) 的结果:
G(n)=⎧⎩⎨⎪⎪0G(n−1)+G(n−2)+Match(b+a)G(n−1)+G(n−2)+Match(a+b)(n≤匹配串的长度)(n是b之后的第奇数个串)(n是b之后的第偶数个串)
参考代码
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
#define LLD long long int
string a, b;
string word;
int len;
LLD serach(string &st, string &word)
{
int l1 = st.length();
int l2 = word.length();
LLD ret = 0;
bool flag;
for (int i = 0; i < l1; i++) {
flag = true;
for (int j = 0; j < l2; j++)
if (st[i+j] != word[j]) {
flag = false;
break;
}
if (flag == true)
ret++;
}
return ret;
}
void makeAns(int n, LLD a, LLD b, LLD da, LLD db)
{
int times = 0;
while(times < n) {
if (times % 2)
a += b+da;
else
b += a+db;
times++;
}
if (times % 2)
printf("%lld\n", b);
else
printf("%lld\n", a);
}
int main()
{
int n;
int ca = 1;
while(scanf("%d", &n) != EOF) {
printf("Case %d: ", ca++);
a = "0";
b = "1";
cin >> word;
len = word.length();
int times = 2;
if (n == 0) {
printf("%lld\n", serach(a, word));
continue;
}
if (n == 1) {
printf("%lld\n", serach(b, word));
continue;
}
while ((a.length() < len || b.length() < len) && times <= n) {
if (times % 2) {
b = a+b;
} else {
a = b+a;
}
times++;
}
if (times == n+1) {
if (times % 2)
printf("%lld\n", serach(a, word));
else
printf("%lld\n", serach(b, word));
continue;
}
times--;
LLD ser1 = 0, ser2 = 0;
LLD addser1 = 0, addser2 = 0;
string tmpstr1, tmpstr2;
tmpstr1 = a+b;
tmpstr2 = b+a;
ser1 = ser2 = addser1 = addser2 = -1;
ser1 = serach(a, word);
ser2 = serach(b, word);
addser1 = serach(tmpstr1, word)-ser1-ser2;
addser2 = serach(tmpstr2, word)-ser1-ser2;
if (!(times % 2))
makeAns(n-times, ser1, ser2, addser2, addser1);
else
makeAns(n-times, ser2, ser1, addser1, addser2);
}
return 0;
}