3

I have a function code for string comparison as below :

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>

int max=0;

int calcMis(char *string,int i, int j,int len)
{
     int mis=0;
     int k=0;
     while(k<len)
     {
             if(string[i+k]!=string[j+k])
                mis+=1;
             if((mis+len-k-1)<=max)
                 return 1;
             else if(mis>max)
                 return 0;
             k=k+1;
     }
}

int main()
{
    char *input=malloc(2000*sizeof(char));
    scanf("%d",&max);
    scanf("%s",input);
    int c=0,i,j,k,x,mis=0;
    int len=strlen(input);
    i=0;
    while(i<len-1)
    {
        j=i;
        while(j<len-1)
         {
             k=i+1;
             x=j-i+1;
             if(x<=max)
                 c=c+len-k-x+1;
             else
                while(k+x<=len)
                {
                  if(strncmp(input+i,input+k,x+1)==0)
                   {
                      if(max>=0)
                          c=c+x;
                   }
                  else
                   c+=calcMis(input,i,k,x);
                  k=k+1;
                }       
            j=j+1;
         }
        i=i+1;
    }   
    printf("%d",c);
    return 0;   
}  

This codes is the solution for the question :

Given a string S and and integer K, find the integer C which equals the number of pairs of substrings(S1,S2) such that S1 and S2 have equal length and Mismatch(S1, S2) <= K where the mismatch function is defined below.

eg : abc then the substrings are {a,ab,abc,b,bc,c}

Is there any better method than this. Is there any optimizations possible in this code?

4

2 回答 2

1

这是一个可能有帮助的想法。首先,比较字符串中的所有字符对:

void compare_all(char* string, int length, int* comp)
{
    for (int i1 = 0; i1 < length; ++i1)
        for (int i2 = 0; i2 < length; ++i2)
            result[i1 * length + i2] = (string[i1] != string[i2]);
}

这里comp表示一个包含值 0 和 1 的方阵。每对子串对应于该矩阵中的对角线部分。例如,对于字符串“testing”,矩阵的以下部分表示子字符串“tes”和“tin”。

. . . O . . .
. . . . O . .
. . . . . O .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .

您必须计算有多少部分的元素总和不超过k. 为此,请逐一检查与主对角线平行的所有对角线。为了不计算两次,只看那些低于(或高于)主对角线的那些(为了简单起见,让我们包括主对角线)。

int count_stuff(int* comp, int n, int k)
{
    int result = 0;
    for (diag = 0; diag < n; ++diag)
    {
        int* first_element_in_diagonal = comp + diag;
        int jump_to_next_element = n + 1;
        int length_of_diagonal = n - diag;
        result += count_stuff_on_diagonal(
            first_element_in_diagonal,
            jump_to_next_element,
            length_of_diagonal,
            k);
    }
    return result;
}

现在,问题是一个简单得多的问题:找到整数序列中的部分数,其总和不大于k。最直接的方法是枚举所有这些部分。

int count_stuff_on_diagonal(int* comp, int jump, int n, int k)
{
    int result = 0;
    for (int i1 = 0; i1 < n; ++i1)
        for (int i2 = i1 + 1; i2 < n; ++i2)
        {
            int* first_element_in_section = comp + i1 * jump;
            int mismatches = count_sum_of_section(
                first_element_in_section,
                jump,
                i2 - i1);
            if (mismatches <= k)
                ++result;
        }
    return result;
}

为了提高计算一段连续整数之和的速度,建立一个累积和表;在 0 和 1 的矩阵上使用它。

(请原谅我没有使用const和 VLA,以及偶尔的语法错误)。

于 2013-08-11T19:18:25.350 回答
1

注意:此分析是他/她编辑帖子并包含他/她的其余代码之前进行的。main他/她在原始帖子中没有提及该功能(我在其中提供了答案)。


查看您的代码calcMis,以下是我将进行的一些可读性和样式改进:

  • 从循环中删除所有返回语句。对于小循环来说没什么大不了的,但对于大循环来说就更重要了,因为当它有 3 或 4 个额外的情况要离开循环时,调试起来会更困难。
  • 根据函数的作用重新定义参数。

您的算法按顺序运行,n但我们可以减少它执行的一些操作。我对你的算法的分析如下:

assignment operator            (=)  x4: O(1)
while loop                          x1: O(n), where n is len.
  dereference operator           (*)  x2: O(1)
  less than operator             (<)  x1: O(1)
  does not equal operator        (!=) x1: O(1)
  addition operator              (+)  x4: O(1)
  subtraction operator           (-)  X2: O(1)
  less than or equal to operator (<=) x1: O(1)
  Order: O(n) + 2 * O(1) + O(1) + O(1) + 4 * O(1) + 2 * O(1) + 1 * O(1) = O(n)
Order: 4 * O(1) + O(n) = O(n)

这是改进的算法(微效率和可读性改进)——仍然是线性顺序,但指令更少,并利用const了编译器的优化:

bool calcMis( char const * const str, int const i, int const j, int const len ) {
  // Checks pre conditions.
  assert( str != NULL );

  // Determines if the length is 0, if so return 0 mismatches.
  if ( len == 0 ) return true;

  // Determines if we are comparing at the same index, if so return 0 mismatches.
  if ( i == j ) return true;

  // Defines an integer mis, holds the number of mismatches.
  int mis = 0;

  // Iterates over the entire string of length len.
  for ( int k = 0; ( k < len ) && ( mis < max ); k++ ) {
    // Determines whether there was a mismatch at positions i and j.
    if ( str[ i + k ] != str[ j + k ] ) mis += 1;
  }

  // Defines a bool result, determines whether we have had too many mismatches.
  bool const result = !( mis > max );

  return result;
}
于 2013-08-11T14:03:01.750 回答