力扣- - 最短回文串(KMP算法)

力扣- - 最短回文串(KMP算法)

一、题目描述

在这里插入图片描述

二、分析之KMP算法

1.暴力法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.KMP算法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.next数组求法1:暴力查找最长的前后缀

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

    vector<int> commpute_next(string pattern)
    {
        vector<int>next(pattern.size() + 1, 0);
        next[0] = -1;
        for (int i = 2; i < next.size(); ++i) 
        {
            for (int j = 1; j < i; ++j) 
            {
                if (pattern.substr(0, j) == pattern.substr(i - j, j)) 
                {
                    next[i] = j;
                }
            }
        }
        return next;
    }
    
    int kmp(string str,string pattern)
    {
        vector<int> next = commpute_next(pattern);
        int i = 0;
        int j = 0;
        while (i < str.size()) 
        {
            if (str[i] != pattern[j]) 
            {
                j = next[j];

				//表示当前没有已匹配字符
                if (j == -1) 
                { 
                    i++; //寻找下一个匹配的pattern首字母
                    j = 0; //指针移到pattern开头
                }
            }
            else
            {
                i++;
                j++;
                if (j == pattern.size()) 
                {
                    return (int) (i - pattern.size());
                }
            }
        }
        return -1;
    }

4.next数组求法2

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

 	#include <iostream>
#include <string>
#include <vector>
using namespace std;

vector<int> GetNext(string& match)
{
    vector<int> next(match.size() + 1,0);
    next[0] = -1;
    
    int i = 2;
    int k = 0;
    while(i < match.size())
    {
        if(match[i - 1] == match[k])
        {
            next[i] = k + 1;
            k = next[i];
            i++;
        }
        else if(k == 0)
        {
            next[i] = 0;
            i++;
        }
        else 
        {
            k = next[k];
        }
    }
    return next;
}

int main()
{
    string str;
    string match;
    while(getline(cin,str))
    {
        getline(cin,match);
        vector<int> next = GetNext(match);
        
        int flag = 1;
        
        int i = 0;
        int j = 0;
        while(i < str.size())
        {
            if(str[i] == match[j])
            {
                i++;
                j++;
                if(j == match.size())
                {
                    flag = 0;
                    cout<<i - match.size()<<" ";
                    j = next[j];
                }
            }
            else
            {
                j = next[j];
                if(j == -1)
                {
                    j = 0;
                    i++;
                }
            }
        }
        if(flag)
            cout<<-1<<endl;
    }
    return 0;
}

5.完整KMP代码

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、题目分析

  • 让我们回到这道题本身,我们可以把题目给定的字符串 s 反转过来,得到 reverse 字符串
  • 然后在 s 和reverse之间加上一个 # 字符作为分割,拼成一个新的pattern字符串
  • 然后用KMP中计算pattern最长前后缀的方法,得到pattern的最长公共前后缀ABA
  • 然后把reverse放在前面,s放在后面,删掉中间重复的一组ABA,就得到结果了
    在这里插入图片描述
  • 因为我们需要得到的只是pattern的next数组中的最后一个值,所以commpute_next只需要返回最后一个值就可以了

四、代码

class Solution {
public:
    int commpute_next(string pattern)
    {
        vector<int>next(pattern.size() + 1, 0);
        next[0] = -1;
        next[1] = 0; // A没有前后缀
        int i = 2; // i表示next数组的索引
        int k = 0;
        while (i < next.size()) 
        {
        	// pattern索引比next索引小1
            if (pattern[i - 1] == pattern[k]) 
            { 
                next[i] = k + 1;
                k = next[i];
                ++i;
            } 
            else if (k == 0)
            {
                next[i] = 0;
                ++i;
            } 
            else
            {
                k = next[k];
            }
        }
        return next[next.size() - 1];
    }

    string shortestPalindrome(string s) {
        if(s == "")
        {
            return "";
        }
        
        string reverse = "";
        for (int i = s.size() - 1; i >= 0; --i) 
        {
            reverse += s[i];
        }
        
        string pattern = s + '#' + reverse;
        int max_len = commpute_next(pattern);
        return reverse.substr(0, reverse.size() - max_len) + s;
    }
};
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页