你有三个字符串 S1,S2,M,且 Sn=Sn-1 +Sn-2,n>2问 M 在 Sn 中出现了多少次,由于出现次数可能太多了,你需要把这个次数对 919260817 取模。运用前缀自动机的c++代码实现
时间: 2024-04-16 13:27:29 浏览: 13
要使用前缀自动机来解决这个问题,我们可以构建一个状态机来处理字符串的前缀,并记录 M 在每个状态中出现的次数。以下是一个使用 C++ 实现前缀自动机的示例代码:
```cpp
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
const int MOD = 919260817;
const int MAX_CHAR = 26;
struct Node {
vector<int> next;
vector<int> cnt;
Node() {
next.resize(MAX_CHAR, -1);
cnt.resize(MAX_CHAR, 0);
}
};
class Trie {
private:
vector<Node> nodes;
vector<int> fail;
public:
Trie() {
nodes.push_back(Node()); // 添加根节点
fail.push_back(0); // 根节点的失败指针为自身
}
void insert(const string& word) {
int current = 0; // 当前状态为根节点
for (char c : word) {
int index = c - 'A'; // 将 M 映射到 0-25 的范围
if (nodes[current].next[index] == -1) {
nodes.push_back(Node()); // 添加新的状态
nodes[current].next[index] = nodes.size() - 1; // 更新转移边
}
current = nodes[current].next[index]; // 进入下一个状态
nodes[current].cnt[index]++; // 更新 M 的出现次数
}
}
void buildFailPointer() {
queue<int> q;
q.push(0); // 根节点入队
while (!q.empty()) {
int current = q.front();
q.pop();
for (int i = 0; i < MAX_CHAR; i++) {
if (nodes[current].next[i] != -1) {
int child = nodes[current].next[i];
int failure = fail[current];
while (failure != 0 && nodes[failure].next[i] == -1) {
failure = fail[failure];
}
if (nodes[failure].next[i] != -1) {
failure = nodes[failure].next[i];
}
fail[child] = failure;
q.push(child);
}
}
}
}
int countOccurrences(const string& target) {
int current = 0; // 当前状态为根节点
int occurrences = 0;
for (char c : target) {
int index = c - 'A'; // 将 M 映射到 0-25 的范围
while (current != 0 && nodes[current].next[index] == -1) {
current = fail[current];
}
if (nodes[current].next[index] != -1) {
current = nodes[current].next[index];
}
occurrences += nodes[current].cnt[index];
}
return occurrences % MOD;
}
};
int main() {
Trie trie;
string S1 = "AB";
string S2 = "BA";
string M = "M";
trie.insert(S1);
trie.insert(S2);
trie.buildFailPointer();
string target;
int n;
cout << "输入要查询的字符串 Sn:" << endl;
cin >> target;
cout << "输入 n 的值:" << endl;
cin >> n;
for (int i = 3; i <= n; i++) {
target = target + trie.countOccurrences(target);
}
int occurrences = trie.countOccurrences(target + M);
cout << "M 在 Sn 中出现的次数为: " << occurrences << endl;
return 0;
}
```
这段代码首先构建了一个 Trie 树,并将字符串 S1 和 S2 插入到 Trie 树中。然后,通过构建失败指针,我们可以在 Trie 树中进行快速匹配。最后,我们通过输入 n 和目标字符串 Sn,使用前缀自动机来计算 M 在 Sn 中出现的次数。
请注意,这里将 M 映射到了 0-25 的范围,你可以根据需要进行相应的修改。同时,这段代码还可以进一步优化和扩展,以满足更复杂的需求。