求给出的模式串中有多少个在文本串中出现过

    1. //trie的指针
    2. int idx;
    3. struct node {
    4. int fail; //失配指针
    5. int ed; //有多少单词以这个节点结尾
    6. int pos[30];//子节点的位置
    7. }ac[N];
    8. //建trie树,向trie树中插入字符串s
    9. void build(string s) {
    10. int len = s.size();
    11. int cur = 0;
    12. for (int i = 0; i < len; i++) {
    13. //若trie树中没有该节点,则构造出该节点
    14. if (!ac[cur].pos[s[i]-'a'])
    15. ac[cur].pos[s[i]-'a'] = ++idx;
    16. //继续向下构造
    17. cur = ac[cur].pos[s[i]-'a'];
    18. }
    19. //标记单词结尾
    20. ac[cur].ed++;
    21. }
    22. void get_fail() {
    23. queue<int> q;
    24. //提前处理第二层的fail指针
    25. for (int i = 0; i < 26; i++) {
    26. if (ac[0].pos[i]) {
    27. //指向根节点
    28. ac[ac[0].pos[i]].fail = 0;
    29. q.push(ac[0].pos[i]);
    30. }
    31. }
    32. //求fail指针
    33. while (q.size()) {
    34. int u = q.front();
    35. q.pop();
    36. //枚举所有子节点
    37. for (int i = 0; i < 26; i++) {
    38. //若子节点存在
    39. if (ac[u].pos[i]) {
    40. //子节点的fail指针指向当前节点的
    41. //fail指针所指向的节点的相同子节点
    42. ac[ac[u].pos[i]].fail = ac[ac[u].fail].pos[i];
    43. q.push(ac[u].pos[i]);
    44. //若子节点不存在
    45. } else {
    46. //当前节点的这个子节点指向当前
    47. //节点fail指针的这个子节点
    48. ac[u].pos[i] = ac[ac[u].fail].pos[i];
    49. }
    50. }
    51. }
    52. }
    53. int ac_query(string s) {
    54. int len = s.size();
    55. int cur = 0, res = 0;
    56. for (int i = 0; i < len; i++) {
    57. //继续下一层
    58. cur = ac[cur].pos[s[i]-'a'];
    59. for (int j = cur; j&&ac[j].ed!=-1; j = ac[j].fail) {
    60. res += ac[j].ed;
    61. ac[j].ed = -1;
    62. }
    63. }
    64. return res;
    65. }
    66. signed main() {
    67. int n;
    68. cin >> n;
    69. string s;
    70. for (int i = 1; i <= n; i++) {
    71. cin >> s;
    72. build(s);
    73. }
    74. ac[0].fail = 0; //结束标志
    75. get_fail(); //求失配指针
    76. string txt;
    77. cin >> txt;
    78. cout << ac_query(txt) << "\n";
    79. return 0;
    80. }