求字符串中两个长度最长且相等的子串

265 篇文章 1 订阅

方法一: 动态规划DP[i][j] 表示以i结尾和以j结尾的字串最长长度是多少

方法二:利用 extend KMP,利用首字母在不同位置时的next数组,找出最长长度。。。

My Summary:

s[a,p-1] = t[0, p-a-1]   -> s[i,p-1]=t[i-a, p-a-1]

t[i-a, next[i-a]+i-a-1] = t[0, next[i-a]-1]

So if next[i-a]+i-a-1 >= p-a-1, extend j,p, extend[i]=j

else extend[i]=next[i-a]

My Code:

  void getNextArr(const char *t, vector<int>& nextarr) {
    int lt = strlen(t);
    nextarr.resize(lt,lt);
    for (int i = 1, j = -1, a = 0, p = 0; i < lt; ++i, --j) {
      if (j < 0 || i + nextarr[i - a] >= p) {
        if (j < 0)  j = 0, p = i;
        while (p < lt && t[p] == t[j]) ++p, ++j;
        nextarr[i] = j, a = i;
      }
      else {
        nextarr[i] = nextarr[i - a];
      }
    }
  }
  void getExtendArr(const char *s, const char *t, vector<int>& extend) {
    int slen = strlen(s), tlen = strlen(t);
    extend.resize(tlen);
    vector<int> nextarr;
    getNextArr(t, nextarr);
    for (int i = 0, j = -1, a = 0, p = 0; i < tlen; ++i, --j) {
      if (j < 0 || i + nextarr[i - a] >= p) {
        if (j < 0) j = 0, p = i;
        while (p < slen && j < tlen && s[p] == t[j]) ++p, ++j;
        extend[i] = j, a = i;
      }
      else {
        extend[i] = nextarr[i - a];
      }
    }
  }


Debug Code:

#include <stdio.h>
#include <iostream>
#include <vector>
using namespace std;


class Solution {
public:

  void getExtendNext(const char *t, int *next) {
    int lt = strlen(t);
    for (int i = 1, j = -1, a, p; i < lt; i++, j--) {
      if (j < 0 || i + next[i - a] >= p) {
        if (j < 0)	j = 0, p = i;
        while (p < lt && t[j] == t[p])	j++, p++;
        next[i] = j, a = i;
      }
      else {
        next[i] = next[i - a];
      }
    }
  }
  void getExtend(const char *s, const char *t, int *extend) {
    int ls = strlen(s), lt = strlen(t);
    int next[100]; getExtendNext(t, next);
    for (int i = 0, j = -1, a, p; i < ls; i++, j--)
    if (j < 0 || i + next[i - a] >= p) {
      if (j < 0)	j = 0, p = i;
      while (p < ls && j < lt && s[p] == t[j])	j++, p++;
      extend[i] = j, a = i;
    }
    else	extend[i] = next[i - a];
  }


  void getNextArr(const char *t, vector<int>& nextarr) {
    int lt = strlen(t);
    nextarr.resize(lt,lt);
    for (int i = 1, j = -1, a = 0, p = 0; i < lt; ++i, --j) {
      if (j < 0 || i + nextarr[i - a] >= p) {
        if (j < 0)  j = 0, p = i;
        while (p < lt && t[p] == t[j]) ++p, ++j;
        nextarr[i] = j, a = i;
      }
      else {
        nextarr[i] = nextarr[i - a];
      }
    }
  }
  void getExtendArr(const char *s, const char *t, vector<int>& extend) {
    int slen = strlen(s), tlen = strlen(t);
    extend.resize(tlen);
    vector<int> nextarr;
    getNextArr(t, nextarr);
    for (int i = 0, j = -1, a = 0, p = 0; i < tlen; ++i, --j) {
      if (j < 0 || i + nextarr[i - a] >= p) {
        if (j < 0) j = 0, p = i;
        while (p < slen && j < tlen && s[p] == t[j]) ++p, ++j;
        extend[i] = j, a = i;
      }
      else {
        extend[i] = nextarr[i - a];
      }
    }
  }
  char *strStr(char *haystack, char *needle) {
    // Note: The Solution object is instantiated only once and is reused by each test case.
    if (needle == NULL || haystack == NULL)
      return NULL;
    int i = 0, j = -1, needlelen = strlen(needle), haystacklen = strlen(haystack);
    if (needlelen > haystacklen)
      return NULL;
    if (needlelen == 0)
      return haystack;

    vector<int> next(needlelen + 1, -1);
    while (needle[i]) {
      if (j == -1 || needle[i] == needle[j]) {
        ++i;
        ++j;
        next[i] = j;
      }
      else
        j = next[j];
    }
    i = 0;
    j = 0;
    while (haystack[i]) {
      if (j == -1 || haystack[i] == needle[j]) {
        ++i;
        ++j;
        if (needle[j] == '\0')
          return haystack + i - j;
      }
      else
        j = next[j];
    }
    return NULL;
  }
};
int main() {
  Solution solution;
  const char *ch = "aaaaabbb";
  const char *s = "aaaaabbb";
  const char *t = "aaaaac";

  int nextarr[8];
  vector<int> next, extend;

  //solution.getNextArr(ch, next);
  //solution.getExtendNext(ch, nextarr);
  solution.getExtend(s, t, nextarr);
  solution.getExtendArr(s, t, extend);
  
  return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值