C语言中的字符串操作与数组操作

C语言中的字符串操作与数组操作,c,arrays,string,algorithm,hash,C,Arrays,String,Algorithm,Hash,我正在解决一个字符串的排列问题-给定两个字符串s1和s2,如果s2包含s1的排列,则编写一个函数返回true。换句话说,第一个字符串的一个排列是第二个字符串的子字符串 例1: 输入:s1=“ab”s2=“eidbaooo” 输出:真 例2: 输入:s1=“ab”s2=“eidboaoo” 输出:False 有一种基于数组的解决方案,它存储子字符串中每个字母的出现频率,并每次将其与给定的子字符串进行比较。这个解决方案比我的运行得快。我不明白为什么,因为我正在对数组执行具有O(1)访问时间的字符串字

我正在解决一个字符串的排列问题-给定两个字符串s1和s2,如果s2包含s1的排列,则编写一个函数返回true。换句话说,第一个字符串的一个排列是第二个字符串的子字符串

例1: 输入:s1=“ab”s2=“eidbaooo” 输出:真

例2: 输入:s1=“ab”s2=“eidboaoo” 输出:False

有一种基于数组的解决方案,它存储子字符串中每个字母的出现频率,并每次将其与给定的子字符串进行比较。这个解决方案比我的运行得快。我不明白为什么,因为我正在对数组执行具有O(1)访问时间的字符串字母加法。两种解决方案都具有相同限制的滑动窗口。 那么,发生了什么?为什么我的解决方案较慢

    int findSum(char *string, int substringLength);
    bool checkInclusion(char * s1, char * s2){
        int substringLength = strlen(s1), substringSum = findSum(s1, substringLength);
        int stringLength = strlen(s2);
        if (stringLength < substringLength) return false;
        for (int i = 0; i < stringLength - substringLength + 1; i++, s2++)
        {
           int currentSum = findSum(s2, substringLength);
           if (currentSum == substringSum) return true;
        }
        return false;
    }

    int primes[26] = {2, 599, 23, 809, 11, 47, 3089, 853, 337, 1013, 13, 107, 787, 7, 383, 151, 1493, 
    947, 877, 2141, 431, 211, 59, 911, 23099, 307};
    int findSum(char *string, int substringLength)
    {
       int sum = 0;
       for (int i = 0; i < substringLength; i++)
       {
           sum += primes[*(string + i) - 'a'];
       }
       return sum;
    }
int findSum(char*string,int substringLength);
布尔检查包含(字符*s1,字符*s2){
int substringLength=strlen(s1),substringSum=findSum(s1,substringLength);
int stringLength=strlen(s2);
if(stringLength
基于数组的解决方案的运行时为O(n),因为它在每个字符串上循环一次。但是,您的解决方案的运行时为O(n*m),其中n和m是两个字符串的长度。在
checkInclusion
中找到的
for
循环中,调用
findSum
,它有自己的
for
循环


实际上,您不需要反复调用
findSum
。您只需减去每个字符的值即可。

解决方案:

  • 获取
    s1中所有字符的地图
  • 现在将
    s2
    中的字符映射从索引0移到索引
    len(s1)-1
  • 如果在这个位置,两张地图相等,您的工作就完成了
  • 否则,对于每个新字符,将其添加到
    s2
    映射中,并从同一映射中删除
    i-len(s1)
    字符
通用解决方案模板:


在所有这些问题中,您首先从较小字符串中所有字符的映射和
len(s1)
窗口开始。当您遇到来自
s2
的新字符时,将窗口移动1,即将两个边界移动1。

要解决此问题,我们将按照以下步骤进行操作−

  • 创建大小为26的两个矢量cnt1和cnt2
  • 对于0到s1范围内的i
    • 将cnt1[s1[i]–a]的值增加1
  • j:=0且要求:=s1的尺寸
  • 对于0到s2大小范围内的i
    • x:=s2[I]
    • 将cnt2[x–“a”]增加1

    • 如果cnt1[x–“a”]和cnt2[x–“a”],您会问为什么此代码比未显示的另一段代码慢?为什么您希望总和相等?如果这两个字符串是
      ab
      bca
      ,那么在
      for
      循环中的哪个点上,总和会相等?哇,这确实加快了我的算法,非常感谢!这是一个很好的建议。