• 李春葆、严蔚敏关于KMP算法的next数组值差1


    【算法解析】
    曾经在 https://blog.csdn.net/hnjzsyjyj/article/details/127086502 提到,在KMP算法的众多实现中,有多种定义next数组的方式。所以在使用和查看别人代码时,要特别注意KMP算法的next数组的定义,以免发生混淆。如:
    • 严蔚敏《数据结构》将模式串下标从1开始计数,故定义next[1]=0,next[2]=1;
    • 李春葆《数据结构》将模式串下标从0开始计数,故定义next[0]=-1,next[1]=0。

    由于字符串的下标在C++中从0开始,因此在利用C++进行KMP算法的设计中,将next数组下标从0开始考虑,是很自然的事情。据此,建议选择李春葆《数据结构》中关于模式串下标的定义,即从0开始考虑,据此可定义next[0]=-1,next[1]=0。之后,按照“
    (1)若第i-1位的字符与第j位的字符相等,则next[i]=j+1; (2)若直到第0位依然没有字符与第i-1位的字符相等,则next[i]=0”构建next数组。

    通过观察,发现“
    李春葆、严蔚敏关于KMP算法的next数组值差1”。这就给出了启发。即:
    如果李春葆定义法的next数组值(以“-1 0 ”开头),利用 cout< 那么严蔚敏定义法的next数组值(以“0 1”开头),便可利用 
    cout<输出。
    也就是说,
    仅需修改一条语句,便可复用代码,实现李春葆定义法、严蔚敏定义法中next数组值的输出。

    【输出李春葆定义法next数组值的算法代码】

    1. #include
    2. using namespace std;
    3. const int maxn=100;
    4. int ne[maxn];
    5. void getNext(string s) {
    6. int len=s.length();
    7. int i=0, j=-1;
    8. ne[0]=-1;
    9. while(i
    10. if(j==-1 || s[i]==s[j]) {
    11. ne[++i]=++j;
    12. } else j=ne[j];
    13. }
    14. }
    15. int main() {
    16. string T;
    17. getline(cin,T);
    18. getNext(T);
    19. for(int i=0; ilength(); i++) {
    20. cout<" ";
    21. }
    22. return 0;
    23. }
    24. /*
    25. input: ababaaababaa
    26. output: -1 0 0 1 2 3 1 1 2 3 4 5
    27. */


    【输出严蔚敏定义法next数组值的算法代码】

    1. #include
    2. using namespace std;
    3. const int maxn=100;
    4. int ne[maxn];
    5. void getNext(string s) {
    6. int len=s.length();
    7. int i=0, j=-1;
    8. ne[0]=-1;
    9. while(i
    10. if(j==-1 || s[i]==s[j]) {
    11. ne[++i]=++j;
    12. } else j=ne[j];
    13. }
    14. }
    15. int main() {
    16. string T;
    17. getline(cin,T);
    18. getNext(T);
    19. for(int i=0; ilength(); i++) {
    20. cout<1<<" ";
    21. }
    22. return 0;
    23. }
    24. /*
    25. input: ababaaababaa
    26. output: 0 1 1 2 3 4 2 2 3 4 5 6
    27. */


    【另一种代码:i=1,j=0】

    1. #include
    2. using namespace std;
    3. const int maxn=100;
    4. int ne[maxn];
    5. void getNext(string s) {
    6. int len=s.length();
    7. int i=1, j=0; //int i=0, j=-1;
    8. ne[1]=0; //ne[0]=-1;
    9. while(i
    10. if(j==0 || s[i-1]==s[j-1]) { //if(j==-1 || s[i]==s[j])
    11. ne[++i]=++j;
    12. } else j=ne[j];
    13. }
    14. }
    15. int main() {
    16. string T;
    17. getline(cin,T);
    18. getNext(T);
    19. for(int i=1; i<=T.length(); i++) { //for(int i=0; i
    20. cout<" "; //cout<
    21. }
    22. return 0;
    23. }
    24. /*
    25. input: ababaaababaa
    26. output: 0 1 1 2 3 4 2 2 3 4 5 6
    27. */


    【参考文献】
    https://blog.csdn.net/hnjzsyjyj/article/details/127086502
    https://blog.csdn.net/hnjzsyjyj/article/details/127105603
    https://blog.csdn.net/hnjzsyjyj/article/details/127112363

  • 相关阅读:
    2023年中国水生植物产业链、产值及市场规模分析[图]
    C高级第2天
    IDLE、Anaconda安装与使用
    编译原理—词法分析、构建DFA、上下文无关文法、LL(1)分析、提取正规式
    581. 最短无序连续子数组
    亥姆霍兹线圈主要用途有哪些
    字符串最大跨距
    2023-09-14 mysql-Item_subselect-分析
    常见漏洞修复方案
    《论文写作》感悟
  • 原文地址:https://blog.csdn.net/hnjzsyjyj/article/details/127114683