簡體   English   中英

至少K不匹配子串?

[英]atmost K mismatch substrings?

我試圖解決這個問題,雖然使用蠻力我能夠解決它,但以下優化的算法給了我一些測試用例的錯誤結果。我試過但不能找到代碼的問題可以任何身體幫我。

問題:給定字符串S和整數K,找到整數C,它等於子串對(S1,S2)的數量,使得S1和S2具有相等的長度,並且不匹配(S1,S2)<= K,其中不匹配函數定義如下。

不匹配功能

不匹配(s1,s2)是S1和S2中的字符不同的位置的數量。 例如,不匹配(包,男孩)= 2(在第二和第三位置存在不匹配),不匹配(貓,牛)= 2(再次,在第二和第三位置存在不匹配),Mismatch(倫敦, Mumbai)= 6(因為兩個字符串中每個位置的字符都不同)。 倫敦的第一個角色是'L',而孟買的第一個角色是'M',倫敦的第二個角色是'o',而孟買的'u'是 - 等等。

int main() {

int k;
char str[6000];
cin>>k;
cin>>str;
int len=strlen(str);
int i,j,x,l,m,mismatch,count,r;

count=0;

 for(i=0;i<len-1;i++)
   for(j=i+1;j<len;j++)
   {  mismatch=0;
     for(r=0;r<len-j+i;r++)
   {  

       if(str[i+r]!=str[j+r])
         { ++mismatch;
           if(mismatch>=k)break;
         }
    if(mismatch<=k)++count;
   } 
  }
cout<<count;
return 0;
}

示例測試用例

  1. 測試用例(傳遞上述代碼)

     **input** 0 abab **output** 3 
  2. 測試用例(上述代碼失敗

     **input** 3 hjdiaceidjafcchdhjacdjjhadjigfhgchadjjjbhcdgffibeh **expected output** 4034 **my output** 4335 

你有兩個錯誤。 第一,

for(r=1;r<len;r++)

應該

for(r=1;r<=len-j;r++)

否則,

str[j+r]

在某些時候會開始比較空終止符之后的字符( 超出字符串的結尾)。 最大的r可以是從第j個索引到最后一個字符的剩余字符數。

第二,寫作

str[i+r]

str[j+r]

跳過第i和第j個字符的比較,因為r總是至少為1 你應該寫

for(r=0;r<len-j;r++)

您有兩個基本錯誤。 當不匹配> = k而不是不匹配> k(不匹配== k是可接受的數字)而你讓r變得太大時,你正在退出。 這些在相反方向上扭曲了最終計數但是,如您所見,第二個錯誤“獲勝”。

真正的內循環應該是:

for (r=0; r<len-j; ++r)
{
     if (str[i+r] != str[j+r])
     {
           ++mismatch;
           if (mismatch > k)
                break;
      }
      ++count;
 }

r是子字符串的索引,j + r必須小於len才能對右子字符串有效。 由於i <j,如果str [j + r]有效,那么它是str [i + r],所以不需要讓我參與上限計算。

此外,您希望在不匹配> k時斷開,而不是在> = k,因為允許k不匹配。

接下來,如果在增加不匹配后測試過多的不匹配,則在計數之前不必再次測試它。

最后,r <len-j(而不是<=)的上限意味着不會將尾隨的'\\ 0'字符作為str [j + r]子字符串的一部分進行比較。 當j + r> = len時,你正在比較它和更多,但是當第一次發生時,不匹配小於k。


注意:您詢問了更快的方法。 有一個,但編碼更多涉及。 使外部循環在起始索引值之間的差異增量上。 (0 <delta <len)然后,用以下內容計算所有可接受的匹配:

count = 0;
for delta = 1 to len-1
    set i=0; j=delta; mismatches=0; r=0; 
    while j < len
        .. find k'th mismatch, or end of str:
        while mismatches < k and j+r&ltlen
            if str[i+r] != str[j+r] then mismatches=mismatches+1
            r = r+1
        end while
        .. extend r to cover any trailing matches:
        while j+r<len and str[i+r]==str[j+r]
            r + r+1
        end while

        .. arrive here with r being the longest string pair starting at str[i]
        .. and str[j] with no more than k mismatches. This loop will add (r) 
        .. to the count and advance i,j one space to the right without recounting
        .. the character mismatches inside.  Rather, if a mismatch is dropped off
        .. the front, then mismatches is decremented by 1.
        repeat
            count = count + r
            if str[i] != str[j] then mismatches=mismatches-1
            i = i+1, j = j+1, r = r-1
        until mismatches < k
    end if
end while

這是偽代碼,也是偽錯誤的。 一般的想法是比較所有子串,其中起始索引在一次通過,開始和左側相差△,並且增加子串長度r直到達到源串的末尾或者看到k + 1個不匹配。 也就是說,str [j + r]要么是字符串的結尾,要么是右子字符串中的駝峰向后突破的不匹配位置。 這使得r子串具有從str [i]和str [j]開始的k或更少的不匹配。

因此,計算這些r子串並移動到下一個位置i = i + 1,j = j + 1和新長度r = r-1,如果從左側丟棄不相等的字符,則減少不匹配計數。

應該很容易看出,在每個循環中,r增加1或j增加1並且(j + r)保持不變。 j和(j + r)都將在O(n)時間內到達len,所以整個事物都是O(n ^ 2)。

編輯:我修復了r的處理,所以上面應該更加錯誤。 對O(n ^ 2)運行時的改進可能會有所幫助。

重新編輯:修復了評論錯誤。 重新編輯:算法中出現更多拼寫錯誤,大多數錯配拼寫錯誤並且增加2而不是1。

@Mike我的邏輯有一些修改,這里是正確的代碼...

#include<iostream>
#include<string>
using namespace std;
int main()
{
long long int k,c=0;
string s;
cin>>k>>s;
int len = s.length();
for(int gap = 1 ; gap < len; gap ++)
{
    int i=0,j=gap,mm=0,tmp_len=0; 


        while (mm <=k && (j+tmp_len)<len)
        {
            if (s[i+tmp_len] != s[j+tmp_len])
                mm++;
            tmp_len++;
        }
       // while (((j+tmp_len)<len) && (s[i+tmp_len]==s[j+tmp_len]))
         //   tmp_len++;
        if(mm>k){tmp_len--;mm--;} 
        do{
            c = c + tmp_len ;
            if (s[i] != s[j]) mm--;

                i++;
                j++;

            tmp_len--;
            while (mm <=k && (j+tmp_len)<len)
            {
            if (s[i+tmp_len] != s[j+tmp_len])
                mm++;
            tmp_len++;
            }
            if(mm>k){tmp_len--;mm--;} 
        }while(tmp_len>0);

}
cout<<c<<endl;
return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM