簡體   English   中英

如何計算兩個字符串之間共有的不同字符的數量?

[英]How to count the number of distinct characters in common between two strings?

程序如何計算兩個字符串之間共有的不同字符數?

例如,如果s1="connect"s2="rectangle" ,則計數顯示為5,但正確答案為4; 重復字符只能計數一次。 如何修改此代碼,以便計數正確?

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

int main()
{
    int i,j,count=0;
    char s1[100],s2[100];
    scanf("%s",s1);//string 1 is inputted
    scanf("%s",s2);//string 2 is taken as input
    for(i=1;i<strlen(s1);i++)
    {
        for(j=1;j<strlen(s2);j++)
        {
            if(s1[i]==s2[j])//compare each char of both the strings to find common  letters
            {
                count++;//count the common  letters
                break;
            }
        }

    }
    printf("%d",count);//display the count

}

該程序將兩個字符串作為輸入,並顯示這些字符串中常見字符的計數。 請讓我知道這段代碼有什么問題。

如果必須忽略重復字符,則程序必須“記住”已經遇到的字符。 您可以通過將已處理的字符存儲到字符數組中,然后在處理其他字符時查詢該數組來做到這一點。

您可以使用計數器變量來跟蹤常見字符的數量,例如

int ctr=0;
char s1[100]="connect", s2[100]="rectangle", t[100]="";

此處, t是將存儲檢查的字符的字符數組。 使它的大小與其他2個字符數組中最大字符的大小相同。

現在使用像

for(int i=0; s1[i]; ++i)
{
    if(strchr(t, s1[i])==NULL && strchr(s2, s1[i])!=NULL)
    {
        t[ctr++]=s1[i];
        t[ctr]=0;
    }
}

t最初有一個空字符串。 通過循環的主體將t中以前不存在的字符添加到循環中,只有當被檢查的字符(即s1[i] )不在t但存在於另一個字符串(即s2 )中時,才會執行該循環)。

strchr()是帶有原型的函數

char *strchr( const char *str, int c );

strchr()在由str指向的字符串中找到c的第一個匹配項。 如果str不存在c則返回NULL


您使用scanf()可能會引起麻煩。

采用

scanf("%99s",s1);

(其中99比數組s1的大小小s1 )而不是

scanf("%s",s1);

以防止溢出問題。 並檢查scanf()的返回值,看看它是否為1 scanf()返回成功進行分配的次數。

或使用fgets()讀取字符串。

閱讀這篇文章以了解更多信息。

並注意數組索引從0開始。 因此,在循環中,不會檢查字符串的第一個字符。

所以應該是這樣的

for(i=0;i<strlen(s1);i++)

代替

for(i=1;i<strlen(s1);i++)

這是一種避免二次O(N²)或三次O(N³)時間算法的解決方案-它是線性時間,需要對每個輸入字符串中的每個字符進行一次訪問。 該代碼使用一對常量字符串,而不要求用戶輸入。 另一種選擇是從命令行獲取兩個參數,然后進行比較。

#include <limits.h>
#include <stdio.h>

int main(void)
{
    int count = 0;
    char bytes[UCHAR_MAX + 1] = { 0 };
    char s1[100] = "connect";
    char s2[100] = "rectangle";

    for (int i = 0; s1[i] != '\0'; i++)
        bytes[(unsigned char)s1[i]] = 1;

    for (int j = 0; s2[j] != '\0'; j++)
    {
        int k = (unsigned char)s2[j];
        if (bytes[k] == 1)
        {
            bytes[k] = 0;
            count++;
        }
    }

    printf("%d\n",count);
    return 0;
}

第一回路記錄哪些字符在本s1通過的適當元素設置bytes陣列1 字符串中是否有重復的字符並不重要。

第二個循環檢測s2中的字符何時在s1並且之前在s2s2 ,然后通過將bytes的條目設置回0來遞增count並將該字符標記為“不再相關”。

最后,它顯示計數4 (末尾有換行符)。

如果平台上的普通char類型是帶符號類型,並且輸入字符串中的任何字節在0x80..0xFF范圍內(如果-128..-1則等於-128..-1 (unsigned char)則必須使用(unsigned char)轉換char類型已簽名)。 使用否定下標不會帶來幸福。 該代碼還假定您使用的是單字節代碼集,而不是多字節代碼集(例如UTF-8)。 如果您要處理多字節字符,則計數將關閉。


問題中的代碼至少是二次算法,因為對於s1每個字符,它可以逐步遍歷s2所有字符,只是發現它沒有發生。 僅此一項就需要O(N²)時間。 這兩個循環還使用基於strlen(s1)strlen(s2) ,並且如果優化器無法識別每次返回的值相同,則代碼可以在每個循環的每次迭代中掃描每個字符串。

類似地,我鍵入的其他兩個答案中的代碼( 答案1答案2 )也由於它們的循環結構而二次冪或更差。

在每個字符串100個字符的范圍內,您可能不會輕易發現差異,尤其是在單次計數迭代中。 如果字符串更大(數千或數百萬個字節),並且重復執行計數,那么線性算法和二次(或更差)算法之間的差異將更大並且更容易檢測到。

我還使用Big-O標記略微加快了速度。 我假設N是字符串的大小,並且它們的大小足夠相似,以至於將N₁( s1的長度)近似等於N 2( s2的長度)不會是一個主要問題。 。 “二次”算法可以更正式地表示為O(N₁•N 2),而線性算法為O(N₁+ N 2)。

根據您期望的輸出,您應該跟蹤第二個字符串中使用的字符。 您可以按照以下步驟實現:

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

int main()
{
    int i, j, count = 0, skeep;
    char s1[100], s2[100], s2Used[100]{0};
    scanf("%s", s1);    //string 1 is inputted
    scanf("%s", s2);    //string 2 is taken as input
    for (i = 0; i<strlen(s1); i++)
    {
        skeep = 0;
        for (j = 0; j < i; j++)
        {
            if (s1[j] == s1[i])
            {
                skeep = 1;
                break;
            }
        }

        if (skeep)
            continue;

        for (j = 0; j<strlen(s2); j++)
        {
            if (s1[i] == s2[j] && s2Used[j] == 0)   //compare each char of both the strings to find common  letters
            {
                //printf("%c\n", s1[i]);
                s2Used[j] = 1;
                count++;//count the common  letters
                break;
            }
        }

    }
    printf("%d", count);//display the count
}

暫無
暫無

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

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