This question is to give N strings and then find the longest substring, which appears in at least N/2 + 1 strings,
If there are multiple such substrings, output them in Lexicographic Order. If there is no such substrings, output ?.
This is the example 11 in Luo Sui's thesis. He describes the specific solution. The suffix array is used for such a question.
It's easy to use a suffix array.
The solution to this question is still a model-based approach. Concatenate N strings into one. Note that they cannot be added in the middle.
The Separator in any string, and then the sa array and height array are created.
The last two answers are divided into two parts. Based on the answer, that is, the length of the substring is used to group the height array.
In the example 3 in the essay, the idea is to enumerate the height array from the end to the end, and put the continuous values greater than or equal to the answer into a group,
If it is smaller than the answer, it is a new group. You need to find some groups for this question. The suffix can appear in N original
In the string, the common prefix of this group is the nMid characters starting with sa [I] (nMid is the length of the substring obtained when the nMid is binary ).
This question requires output of multiple sub-strings that meet the requirements in Lexicographic Order, so it is troublesome. In the Check function
Record these substrings, and sort the output answers, and then unique. Because they are searched in the order of the height array,
Sa [I] has already sorted the answer, so the answer sorting process can be omitted, but it must be unique. Check the Function
When traversing the height array, you will know that duplicate substrings may occur...
The Code is as follows:
# Include <stdio. h>
# Include <string. h>
# Include <algorithm>
Using namespace std;
Const int MAX_N = 110;
Const int MAX_L = 1010;
Const int MAX = MAX_N * MAX_L;
Int nAns;
Char szStr [MAX_L];
Char szAns [MAX] [MAX_L];
Char * pszAns [MAX];
Int nNum [MAX];
Int nLoc [MAX];
Bool bVis [MAX_N];
Int sa [MAX], rank [MAX], height [MAX];
Int wa [MAX], wb [MAX], wv [MAX], wd [MAX];
Bool CmpStr (const char * pszOne, const char * pszTwo)
{
Return strcmp (pszOne, pszTwo) <0;
}
Bool character STR (const char * pszOne, const char * pszTwo)
{
Return strcmp (pszOne, pszTwo) = 0;
}
Int cmp (int * r, int a, int B, int l)
{
Return r [a] = r [B] & r [a + l] = r [B + l];
}
// Multiplier algorithm. r indicates the array to be matched, n indicates the total length, and m indicates the string range.
Void da (int * r, int n, int m)
{
Int I, j, p, * x = wa, * y = wb;
For (I = 0; I <m; ++ I) wd [I] = 0;
For (I = 0; I <n; ++ I) wd [x [I] = r [I] ++;
For (I = 1; I <m; ++ I) wd [I] + = wd [I-1];
For (I = n-1; I> = 0; -- I) sa [-- wd [x [I] = I;
For (j = 1, p = 1; p <n; j * = 2, m = p)
{
For (p = 0, I = n-j; I <n; ++ I) y [p ++] = I;
For (I = 0; I <n; ++ I) if (sa [I]> = j) y [p ++] = sa [I]-j;
For (I = 0; I <n; ++ I) wv [I] = x [y [I];
For (I = 0; I <m; ++ I) wd [I] = 0;
For (I = 0; I <n; ++ I) wd [wv [I] ++;
For (I = 1; I <m; ++ I) wd [I] + = wd [I-1];
For (I = n-1; I> = 0; -- I) sa [-- wd [wv [I] = y [I];
Swap (x, y );
For (p = 1, x [sa [0] = 0, I = 1; I <n; ++ I)
{
X [sa [I] = cmp (y, sa [I-1], sa [I], j )? P-1: p ++;
}
}
}
// Calculate the height Array
Void calHeight (int * r, int n)
{
Int I, j, k = 0;
For (I = 1; I <= n; ++ I) rank [sa [I] = I;
For (I = 0; I <n; height [rank [I ++] = k)
{
If (k) -- k;
For (j = sa [rank [I]-1]; r [I + k] = r [j + k]; k ++ );
}
}
Bool Check (int nMid, int nN, int nK)
{
Int nCnt = 0;
Int nNo = 0;
Memset (bVis, false, sizeof (bVis ));
For (int I = 1; I <= nN; ++ I)
{
If (height [I] <nMid)
{
NCnt = 0;
Memset (bVis, false, sizeof (bVis ));
}
Else
{
If (! BVis [nLoc [sa [I-1])
{
++ NCnt;
BVis [nLoc [sa [I-1] = true;
}
If (! BVis [nLoc [sa [I])
{
++ NCnt;
BVis [nLoc [sa [I] = true;
}
If (nCnt = nK)
{
For (int j = 0; j <nMid; ++ j)
{
SzAns [nNo] [j] = nNum [sa [I] + j];
}
SzAns [nNo] [nMid] = 0;
++ NNo;
NCnt = 0;
}
}
}
If (nNo> 0) nAns = nNo;
Return nNo> 0;
}
Int main ()
{
Int nN;
Bool bFirst = true;
While (scanf ("% d", & nN), nN)
{
If (bFirst) bFirst = false;
Else putchar ('\ n ');
Int nend= 300;
Int nP = 0;
For (int I = 0; I <nN; ++ I)
{
Scanf ("% s", szStr );
Int nLen = strlen (szStr );
For (int j = 0; j <nLen; ++ j)
{
NNum [nP] = szStr [j];
NLoc [nP ++] = I;
}
NNum [nP] = nEnd;
NLoc [nP ++] = nEnd ++;
}
NNum [nP] = 0;
If (nN = 1)
{
Printf ("% s \ n", szStr );
Continue;
}
Da (nNum, nP + 1,500); // 500 is the estimated character set size.
CalHeight (nNum, nP );
Int nLeft = 1, nRight = strlen (szStr );
Int nTemp = 0, nMid;
Int nK = nN/2 + 1;
NAns = 0;
While (nLeft <= nRight)
{
NMid = (nLeft + nRight)> 1;
If (Check (nMid, nP, nK ))
{
NTemp = nMid;
NLeft = nMid + 1;
}
Else nRight = nMid-1;
}
If (nTemp = 0)
{
Printf ("? \ N ");
}
Else
{
For (int I = 0; I <nAns; ++ I)
{
PszAns [I] = szAns [I];
}
// Sort (pszAns, pszAns + nAns, CmpStr );
NAns = unique (pszAns, pszAns + nAns, shortstr)-pszAns;
For (int I = 0; I <nAns; ++ I)
{
Printf ("% s \ n", pszAns [I]);
}
}
}
Return 0;
}