Why this code is giving SIGSEGV error?

link text

The seg fault issue is due to incorrect operation with strings and improper separation between local and global variables.

First, all char a[20] have to be changed to char a[21]. Same for char b[100][20] - it should be char b[100][21]. Per problem statement, the maximum size of the words is 20 characters. That means, however, that in order to store it and operate on it as a string object, we need to allocate 21 characters to reserve an extra space for null-terminated character.

As a follow-up, when making a copy of a string, you have to copy strlen(a)+1 characters in the strncpy call.

Second, when you accumulate the typed words, you keep the count in the global variable o but the accumulation happens in the local array b[100][20]. Therefore on every time call the b[100][20] array is brand new, and it is not in sync with the o counter.

Once all these issues are fixed, you also need to adjust the output since per problem statement an answer for each test case should be on a new line - you have to add \n to printf.

Here’s the adjusted code that gets AC:

#include <stdio.h>
#include <string.h>
int N,o=0,p;
char b[100][21]; // should be global otherwise modifications are
                 // inconsistent with 'o' counter changes
int time(char a[21])
{
    int wt=2;
    for(int i=1;i<strlen(a);i++)
    {
        if(a[i-1]==a[i])
            wt=wt+4;
        else if((a[i-1]=='d'&&a[i]=='f')||(a[i-1]=='f'&&a[i]=='d'))
            wt=wt+4;
        else if((a[i-1]=='j'&&a[i]=='k')||(a[i-1]=='k'&&a[i]=='j'))
            wt=wt+4;
        else
            wt=wt+2;
    }
    for(int j=0;j<o;j++)
    {
        p=strncmp(b[j],a,strlen(a));
        if((p==0) && (strlen(b[j]) == strlen(a)))
        {
            wt=wt/2;
            break;
        }
    }
    strncpy(b[o],a,strlen(a)+1); // +1 is for copying the null-terminating character
    o++;
    return wt;
}
int main()
{
    int j,t=0,sum=0;
    scanf("%d",&t);
    for(int r=0;r<t;r++)
    {
        o = 0;
        sum=0;
        scanf("%d",&N);
        char a[21];
        for(int i=0;i<N;i++)
        {
            scanf("%s",&a);
            sum=sum+time(a);
        }
        printf("%d\n",sum); // the end-of-line was missing in the output
    }
    return 0;
} 

However I would solve the problem a bit differently. As you have seen, operating with strings on character level is quite error-prone. IMHO, it is easier and more robust to operate with strings directly, and also use some of the STL data structures like std::vector and std::set. Here’s how I see a better organized solution:

#include <bits/stdc++.h>
using namespace std;

int solve_word(const string& s) {
    vector<int> hand;
    for(int i=0; i<s.size(); ++i) {
        hand.push_back((s[i]=='d' || s[i]=='f') ? 0 : 1);
    }
    int res = 2;
    for(int i=1; i<s.size(); ++i) {
        res += (hand[i-1] == hand[i]) ? 4 : 2;
    }
    return res;
}

int solve_test_case(const vector<string>& w) {
    const int N = w.size();
    set<string> typed;
    int res = 0;
    for(int i=0; i<N; ++i) {
        int v = solve_word(w[i]);
        if (typed.count(w[i])) {
            v /= 2;
        }
        res += v;
        typed.insert(w[i]);
    }
    return res;
}

int main() {
    int T, N;
    cin >> T;
    for(int t=0; t<T; ++t) {
        cin >> N;
        vector<string> w(N);
        for(int i=0; i<N; ++i) {
            cin >> w[i];
        }
        int res = solve_test_case(w);
        cout << res << endl;
    }
    return 0;
}

Thank you for solution.