コンテンツ
1.strStrを実装します
解決策1:ブルートフォースマッチング(BF)アルゴリズム
int strStr(char * haystack, char * needle){
assert(haystack!=NULL&&needle!=NULL);
int len1=strlen(haystack);
int len2=strlen(needle);
int i=0,j=0;
if(len2==0)
{
return 0;
}
if(len1==0&&len2!=0)
{
return -1;
}
while(i<len1&&j<len2)
{
if(haystack[i]==needle[j])
{
i++;
j++;
}
else{
i=i-j+1;
j=0;
}
}
if(j>=len2)
{
return i-j;
}
else{
return -1;
}
}
解決策2:KMPアルゴリズム
int strStr(char * haystack, char * needle){
if(needle[0]=='\0')
return 0;
int len1=(int)strlen(haystack);
int len2=(int)strlen(needle);
int i=0;
int j=0;
int ans=-1;
int* next=(int*)malloc(sizeof(int)*len2);
getnext(next,needle);
while(i<len1)
{
if(j==-1||haystack[i]==needle[j])
{
++i;
++j;
}
else{
j=next[j];
}
if(j==len2)
{
ans=i-len2;
break;
}
}
return ans;
}
void getnext(int next[],char* needle)
{
next[0]=-1;
int j=0;
int k=-1;
int len=(int)strlen(needle);
while(j<len-1)
{
if(k==-1||needle[j]==needle[k])
{
++j;
++k;
next[j]=k;
}
else{
k=next[k];
}
}
}
ソリューション1とソリューション2の関連する知識ポイントを理解していない場合は、このブログを読んで詳細な説明を参照してください。
解決策3:ハッシュが暴力を加速する
class Solution {
public:
int strStr(string haystack, string needle) {
if(needle=="") return 0;
int n = haystack.size(), m = needle.size();
int hash = 0;
for(auto c: needle){
hash += c -'a';
}
int cur = 0;
for(int i = 0; i < n; i++){
cur += haystack[i] - 'a';
if(i >= m ) cur -= haystack[i-m] - 'a';
if(i >= m-1 && cur == hash && haystack.substr(i-m+1,m) == needle)
return i-m+1;
}
return -1;
}
};
解決策4:
問題解決のアイデア1.2
つのポインターを定義します。ヘッドポインターは干し草の山の配列の頭から始まり、テールポインターの位置は、針の配列の長さ(0 + len2-1)
2によって決まります。 whileループに入ると、ループの終わりの条件は次のようになります。テールポインタがhaystack配列の終わりに到達します
。3。haystack配列がheadで始まり、長さがlen2のサブストリングがneedle配列と同じかどうかを判断します。 。その場合は、この時点でヘッド値を返します
。4.ヘッドポインタとテールポインタで++操作を実行し、ウィンドウサイズを維持します
。5。ループが終了します。これは、マッチングが失敗したことを意味し、-1を返します。
class Solution {
public:
int strStr(string haystack, string needle) {
int len1=haystack.size(),len2=needle.size();
//尾指针的位置由needle数组的长度确定,也就是(0+len2-1)
int head=0,tail=len2-1;
//循环结束的条件是尾指针到达haystack数组的尾部
while(tail<len1){
//判断haystack数组以head为开头,len2为长度的子串和needle数组是否相同
if(haystack.substr(head,len2)==needle) return head;
head++;
tail++;
}
return -1;
}
};
解決策5:C++ライブラリ関数の使用
class Solution {
class Solution {
public:
int strStr(string haystack, string needle) {
if(needle.empty())
return 0;
int pos=haystack.find(needle);
return pos;
}
};
この問題には多くの解決策があるはずです。考えれば、コメント欄にメッセージを残して一緒に話し合うことができます。
2.繰り返される部分文字列
解決策1:KMPアルゴリズム
以下は、私がLikouで見つけたよく理解されているKMPソリューションです。
次の配列が1つ減らず、移動しない方法。詳細については、
コードを参照してください。
次の配列を印刷して、次の配列のルールを確認することを強くお勧めします。これは、理解に役立ちます。 KMPアルゴリズム。
最終的なif判定は、次のように理解できます。
答えがtrueの場合、次のテーブルの最初の数桁(サブストリング)はすべて0であり、次は常にインクリメントされます。Next(n-1)は元のテーブルを格納します。文字列からサブ文字を引いたもの。文字列の長さの値はlen2として記録され、len-len2の値はlen1として記録されます。len1は部分文字列の長さであり、lenで割り切れる必要があります。
//求字符串s的next数组
void Getnext(int *next, char *s, int len)
{
int j=0;
next[0]=0;
for(int i=1; i<len; i++)
{
while(j>0 && s[i]!=s[j])
{
j=next[j-1];
}
if(s[i] == s[j])
{
j++;
}
next[i]=j;
}
}
bool repeatedSubstringPattern(char * s)
{
int len = strlen(s);
if(len == 0) return false;
int *next = (int*)malloc(sizeof(int) * len);
Getnext(next, s, len);
// next[len-1]!=0 代表s字符串有最长的相等前后缀
// len % (len - next[len-1]) == 0
// 代表(数组长度 - 最长相等前后缀的长度)正好可以被数组的长度整除
if(next[len-1]!=0 && len % (len - next[len-1]) == 0)
{
return true;
}
return false;
}
解決策2:列挙メソッド
アイデアとアルゴリズム
長さnnの文字列ssが、長さn'nの部分文字列s's'で構成され、何度も繰り返される場合、nnはn'n'の倍数である必要があります。s's'はssの接頭辞である必要があります。 \ in [n'、n)i∈[n'、n)、s [i] = s [in'] s [i] = s [i−n']があります。つまり、ssの長さn'n'の接頭辞はs's'であり、その後の各位置の文字s [i] s [i]は、その前のn'n番目の文字と同じである必要があります。文字s[in']s [i−n']は同じです。したがって、n'n'を小さいものから大きいものへと列挙し、文字列ssをトラバースして上記の判断を下すことができます。小さな最適化では、部分文字列を少なくとも1回繰り返す必要があるため、n'n'はnnの半分より大きくなることはなく、[1、\ frac{n}{2}の範囲内にある必要があるだけであることに注意してください。 ] [1、2n]n'n'を列挙するだけで十分です。
bool repeatedSubstringPattern(char * s){
int len=strlen(s);
for(int i=1;i*2<=len;i++)
{
if(len%i==0){
bool match=true;
for(int j=i;j<len;j++)
{
if(s[j]==s[j-i])
{
match=true;
}
else{
match=false;
break;
}
}
if(match==true)
{
return true;
}
}
}
return false;
}
解決策3:文字列照合
bool repeatedSubstringPattern(char* s) {
int n = strlen(s);
char k[2 * n + 1];
k[0] = 0;
strcat(k, s);
strcat(k, s);
return strstr(k + 1, s) - k != n;
}