??xml version="1.0" encoding="utf-8" standalone="yes"?>久久久精品人妻一区二区三区蜜桃 ,久久露脸国产精品,久久偷看各类wc女厕嘘嘘http://www.shnenglu.com/csu-yx-2013/archive/2012/10/24/193807.htmlyxyxWed, 24 Oct 2012 12:55:00 GMThttp://www.shnenglu.com/csu-yx-2013/archive/2012/10/24/193807.htmlhttp://www.shnenglu.com/csu-yx-2013/comments/193807.htmlhttp://www.shnenglu.com/csu-yx-2013/archive/2012/10/24/193807.html#Feedback0http://www.shnenglu.com/csu-yx-2013/comments/commentRss/193807.htmlhttp://www.shnenglu.com/csu-yx-2013/services/trackbacks/193807.html   该题貌似可以用后~数组和扩展kmp做,但是好像后缀数组貌似会tleQ改学了?br />一个专门的叫Manacher法的东ѝ。?br />   q又是一个线性改良算法。找到有文章写的不错,链接如下Q?br />http://www.felix021.com/blog/read.php?2040?br />   该算法说h也不是太复杂Q比较容易看懂的那种Q当然是接触q其它字W串法
的前提下了。记得以前就看了看,是没看懂,想不到现在这么快明白了?br />   该算法需要额外的O(N)I间。说h是空间换旉吧?br />   大概的思\是先预处理字W串Q其成Z个长度一定ؓ偶数的串。而且W一个字W?br />?$'Q假?$'没有在原串出现过。然后再在原来的每个字符前面加上'#'Q最后再加个
'#'。比如,abc变成了$#a#b#c#。现在再Ҏ的字W串q行处理?br />   开一个新的数lnRad[MAX]QnRad[i]表示C中第i个位|向左边和向双同时扩展
q且保持对称的最大距R如果求ZnRad数组后,有一个结论,nRad[i]-1恰好表示原串
对应的位|能够扩展的回文子串长度。这个的证明Q应该比较简单,因ؓC基本上是原串
?倍了Q而且C每一个有效字W两侧都有插入的#Q这个找个例子看下就知道是这样了?br />   最重要的是如何求出nRad数组?br />   求这个数l的法也主要是利用了一些间接的l论优化了nRad[i]的初始化倹{比如我们求
nRad[i]的时候,如果知道了i以前的nRad|而且知道了前面有一个位|idQ能够最大的?br />两边扩展距离max。那么有一个结论,nRad[i] 能够初始化ؓmin(nRad[2*id - i], max - i)Q?br />然后再进行递增。关键是如何证明q个Q这个的证明Q对照图片就很清楚了?br />   证明如下Q?br />   ?mx - i > P[j] 的时候,以S[j]Z心的回文子串包含在以S[id]Z心的回文子串中,׃ i ?j 对称Q?br />以S[i]Z心的回文子串必然包含在以S[id]Z心的回文子串中,所以必?P[i] = P[j]Q见下图?br />    
   
   ?P[j] > mx - i 的时候,以S[j]Z心的回文子串不完全包含于以S[id]Z心的回文子串中,但是Z
对称性可知,下图中两个绿框所包围的部分是相同的,也就是说以S[i]Z心的回文子串Q其向右臛_?br />扩张到mx的位|,也就是说 P[i] >= mx - i。至于mx之后的部分是否对Uͼ只能老老实实去匚w了?br />
   
      q个p明得很清楚了。。?br />
      代码如下Q?br />
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

const int MAX = 110010 * 2;
char szIn[MAX];
char szOut[MAX];
int nRad[MAX];

int Proc(char* pszIn, char* pszOut)
{
    int nLen = 1;
    
    *pszOut++ = '$';
    while (*pszIn)
    {
        *pszOut++ = '#';
        nLen++;
        *pszOut++ = *pszIn++;
        nLen++;
    }
    *pszOut++ = '#';
    *pszOut = '\0';
    
    return nLen + 1;
}

void Manacher(int* pnRad, char* pszStr, int nN)
{
    int nId = 0, nMax = 0;
    
    //pnRad[0] = 1;
    for (int i = 0; i < nN; ++i)
    {
        if (nMax > i)
        {
            pnRad[i] = min(pnRad[2 * nId - i], nMax - i);
        }
        else pnRad[i] = 1;
        
        while (pszStr[i + pnRad[i]] == pszStr[i - pnRad[i]])
        {
            ++pnRad[i];
        }
        if (pnRad[i] + i > nMax)
        {
            nMax = pnRad[i] + i;
            nId = i;
        }
    }
}

int main()
{
    while (scanf("%s", szIn) == 1)
    {
        int nLen = Proc(szIn, szOut);
        Manacher(nRad, szOut, nLen);
        int nAns = 1;
        for (int i = 0; i < nLen; ++i)
        {
            nAns = max(nRad[i], nAns);
        }
        printf("%d\n", nAns - 1);
    }
    
    return 0;
}


yx 2012-10-24 20:55 发表评论
]]>
poj 3294 Life Forms 后缀数组求至出现在K个字W串中的最长公共子?/title><link>http://www.shnenglu.com/csu-yx-2013/archive/2012/10/24/193783.html</link><dc:creator>yx</dc:creator><author>yx</author><pubDate>Wed, 24 Oct 2012 07:57:00 GMT</pubDate><guid>http://www.shnenglu.com/csu-yx-2013/archive/2012/10/24/193783.html</guid><wfw:comment>http://www.shnenglu.com/csu-yx-2013/comments/193783.html</wfw:comment><comments>http://www.shnenglu.com/csu-yx-2013/archive/2012/10/24/193783.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/csu-yx-2013/comments/commentRss/193783.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/csu-yx-2013/services/trackbacks/193783.html</trackback:ping><description><![CDATA[   此题是l出N个字W串Q然后求一个最长的子串Q它臛_出现在N/2+1个字W串中,<br />如果有多个这L子串Q按字典序输出,如果没有q样的子Ԍ输出??br />   此题是罗I骞论文里面的例11Q他有讲q具体的解法。要用后~数组做这L题真?br />ҎQ用后缀数组感觉是一仉常纠l的事情了?br />   q个题的解法q是那种模式化的思\。把N个字W串q接成一个,注意中间加不出现?br />M一个字W串中的分隔W,然后建立sa数组和height数组{?br />   最后二分答案,Ҏ{案Q即子串的长度对height数组q行分组Q分l的思\q是|穗<br />骞论文里面例3的思\Q即从到后枚举height数组Q把q箋大于{于{案的值放做一l,<br />一旦小于答案那么就是新的分l。这个题需要找C些分l,其中的后~是能够出现在N个原<br />串中Q这个分l的公共前缀是sa[i]开始的nMid个字W了(nMid是二分时候获得的子串长度)?br />   ׃q个题需要按字典序输出多个满求的子串Q所以麻烦了炏V需要在Check函数里面<br />记录q些子串Q而且输出{案的时候需要排序,再uniqueQ由于是按height数组的顺序查扄Q?br />而sa[i]已经排好序了Q所以排序答案的q程可以省略Q但是必unique。想下Check函数里面<br />遍历height数组的过E就知道可能出现重复的子丌Ӏ。?br /><br />   代码如下Q?br /><div style="background-color: #eeeeee; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all; "><div>#include <stdio.h></div><div>#include <string.h></div><div>#include <algorithm></div><div>using namespace std;</div><div></div><div>const int MAX_N = 110;</div><div>const int MAX_L = 1010;</div><div>const int MAX = MAX_N * MAX_L;</div><div></div><div>int nAns;</div><div>char szStr[MAX_L];</div><div>char szAns[MAX][MAX_L];</div><div>char* pszAns[MAX];</div><div>int nNum[MAX];</div><div>int nLoc[MAX];</div><div>bool bVis[MAX_N];</div><div>int sa[MAX], rank[MAX], height[MAX];</div><div>int wa[MAX], wb[MAX], wv[MAX], wd[MAX];</div><div></div><div>bool CmpStr(const char* pszOne, const char* pszTwo)</div><div>{</div><div>    return strcmp(pszOne, pszTwo) < 0;</div><div>}</div><div></div><div>bool EqualStr(const char* pszOne, const char* pszTwo)</div><div>{</div><div>    return strcmp(pszOne, pszTwo) == 0;</div><div>}</div><div></div><div>int cmp(int* r, int a, int b, int l)</div><div>{</div><div>    return r[a] == r[b] && r[a + l] == r[b + l];</div><div>}</div><div></div><div>//倍增法,r为待匚w数组,n为总长?m为字W串范围</div><div>void da(int* r, int n, int m)</div><div>{</div><div>    int i, j, p, *x = wa, *y = wb;</div><div>    </div><div>    for (i = 0; i < m; ++i) wd[i] = 0;</div><div>    for (i = 0; i < n; ++i) wd[x[i] = r[i]]++;</div><div>    for (i = 1; i < m; ++i) wd[i] += wd[i - 1];</div><div>    for (i = n - 1; i >= 0; --i) sa[--wd[x[i]]] = i;</div><div>    </div><div>    for (j = 1, p = 1; p < n; j *= 2, m = p)</div><div>    {</div><div>        for (p = 0, i = n - j; i < n; ++i) y[p++] = i;</div><div>        for (i = 0; i < n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j;</div><div>        </div><div>        for (i = 0; i < n; ++i) wv[i] = x[y[i]];</div><div>        for (i = 0; i < m; ++i) wd[i] = 0;</div><div>        for (i = 0; i < n; ++i) wd[wv[i]]++;</div><div>        for (i = 1; i < m; ++i) wd[i] += wd[i - 1];</div><div>        for (i = n - 1; i >= 0; --i) sa[--wd[wv[i]]] = y[i];</div><div>        </div><div>        swap(x, y);</div><div>        for (p = 1, x[sa[0]] = 0, i = 1; i < n; ++i)</div><div>        {</div><div>            x[sa[i]] = cmp(y, sa[i - 1], sa[i], j)? p - 1 : p++;</div><div>        }</div><div>    }</div><div>}</div><div></div><div>//求height数组</div><div>void calHeight(int* r, int n)</div><div>{</div><div>    int i, j, k = 0;</div><div>    for (i = 1; i <= n; ++i) rank[sa[i]] = i;</div><div>    for (i = 0; i < n; height[rank[i++]] = k)</div><div>    {</div><div>        if (k) --k;</div><div>        for(j = sa[rank[i] - 1]; r[i + k] == r[j + k]; k++);</div><div>    }</div><div>}</div><div></div><div>bool Check(int nMid, int nN, int nK)</div><div>{</div><div>    int nCnt = 0;</div><div>    int nNo = 0;</div><div>    </div><div>    memset(bVis, false, sizeof(bVis));</div><div>    for (int i = 1; i <= nN; ++i)</div><div>    {</div><div>        if (height[i] < nMid)</div><div>        {</div><div>            nCnt = 0;</div><div>            memset(bVis, false, sizeof(bVis));</div><div>        }</div><div>        else</div><div>        {</div><div>            if (!bVis[nLoc[sa[i - 1]]])</div><div>            {</div><div>                ++nCnt;</div><div>                bVis[nLoc[sa[i - 1]]] = true;</div><div>            }</div><div>            if (!bVis[nLoc[sa[i]]])</div><div>            {</div><div>                ++nCnt;</div><div>                bVis[nLoc[sa[i]]] = true;</div><div>            }</div><div>            if (nCnt == nK)</div><div>            {</div><div>                for (int j = 0; j < nMid; ++j)</div><div>                {</div><div>                    szAns[nNo][j] = nNum[sa[i] + j];</div><div>                }</div><div>                szAns[nNo][nMid] = 0;</div><div>                ++nNo;</div><div>                nCnt = 0;</div><div>            }</div><div>        }</div><div>    }</div><div>    </div><div>    if (nNo > 0) nAns = nNo;</div><div>    return nNo > 0;</div><div>}</div><div></div><div>int main()</div><div>{</div><div>    int nN;</div><div>    bool bFirst = true;</div><div>    </div><div>    while (scanf("%d", &nN), nN)</div><div>    {</div><div>        if (bFirst) bFirst = false;</div><div>        else putchar('\n');</div><div>        </div><div>        int nEnd = 300;</div><div>        int nP = 0;</div><div>        for (int i = 0; i < nN; ++i)</div><div>        {</div><div>            scanf("%s", szStr);</div><div>            int nLen = strlen(szStr);</div><div>            for (int j = 0; j < nLen; ++j)</div><div>            {</div><div>                nNum[nP] = szStr[j];</div><div>                nLoc[nP++] = i;</div><div>            }</div><div>            nNum[nP] = nEnd;</div><div>            nLoc[nP++] = nEnd++;</div><div>        }</div><div>        nNum[nP] = 0;</div><div>        </div><div>        if (nN == 1)</div><div>        {</div><div>            printf("%s\n\n", szStr);</div><div>            continue;</div><div>        }</div><div>        da(nNum, nP + 1, 500);//500是估计的字符集大?/div><div>        calHeight(nNum, nP);</div><div>        </div><div>        int nLeft = 1, nRight = strlen(szStr);</div><div>        int nTemp = 0, nMid;</div><div>        int nK = nN / 2 + 1;</div><div>        nAns = 0;</div><div>        while (nLeft <= nRight)</div><div>        {</div><div>            nMid = (nLeft + nRight) >> 1;</div><div>            if (Check(nMid, nP, nK))</div><div>            {</div><div>                nTemp = nMid;</div><div>                nLeft = nMid + 1;</div><div>            }</div><div>            else nRight = nMid - 1;</div><div>        }</div><div>        if (nTemp == 0)</div><div>        {</div><div>            printf("?\n");</div><div>        }</div><div>        else</div><div>        {</div><div>            for (int i = 0; i < nAns; ++i)</div><div>            {</div><div>                pszAns[i] = szAns[i];</div><div>            }</div><div>            //sort(pszAns, pszAns + nAns, CmpStr);</div><div>            nAns = unique(pszAns, pszAns + nAns, EqualStr) - pszAns;</div><div>            for (int i = 0; i < nAns; ++i)</div><div>            {</div><div>                printf("%s\n", pszAns[i]);</div><div>            }</div><div>        }</div><div>    }</div><div>    </div><div>    return 0;</div><div>}</div><div style="font-size: 13px; "></div></div><img src ="http://www.shnenglu.com/csu-yx-2013/aggbug/193783.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/csu-yx-2013/" target="_blank">yx</a> 2012-10-24 15:57 <a href="http://www.shnenglu.com/csu-yx-2013/archive/2012/10/24/193783.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>poj 1226 Substrings 后缀数组http://www.shnenglu.com/csu-yx-2013/archive/2012/10/23/193741.htmlyxyxTue, 23 Oct 2012 13:11:00 GMThttp://www.shnenglu.com/csu-yx-2013/archive/2012/10/23/193741.htmlhttp://www.shnenglu.com/csu-yx-2013/comments/193741.htmlhttp://www.shnenglu.com/csu-yx-2013/archive/2012/10/23/193741.html#Feedback0http://www.shnenglu.com/csu-yx-2013/comments/commentRss/193741.htmlhttp://www.shnenglu.com/csu-yx-2013/services/trackbacks/193741.html初学后缀数组Q有很多不明白的东西Q此题后~数组的代码在|上也是一把抓?br />   说实话我实q不懂后~数组Q但是后~数组太强大了Q只能硬着头皮照着葫芦ȝ了?br />贴下代码方便以后查阅吧。。?br />   感觉后缀数组的应用最主要的还是height数组Q看懂倍增法排序后缀已经非常困难了?br />然后再理解height数组怎么用也不是一件容易的事情。然后貌似height数组最关键的用法是
枚D某一个长度的子串时候,比如长度为kQ能够用q个k对height数组q行分组Q这个罗I骞
的论文里面有个求不重叠最镉K复子串的例子说明了这个height数组分组的思\Q不q我现在
q是不怎么理解。。?br />  
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

const int MAX_N = 110;
const int MAX_L = MAX_N * MAX_N;
char szStr[MAX_N];
int nNum[MAX_L];
int nLoc[MAX_L];
bool bVisit[MAX_N];
int sa[MAX_L], rank[MAX_L], height[MAX_L];
int wa[MAX_L], wb[MAX_L], wv[MAX_L], wd[MAX_L];

int cmp(int* r, int a, int b, int l)
{
    return r[a] == r[b] && r[a + l] == r[b + l];
}

//倍增法,r为待匚w数组,n为总长?m为字W串范围
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++;
        }
    }
}

//求height数组
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 nLen, int nN)
{
    int nCnt = 0;
    
    memset(bVisit, falsesizeof(bVisit));
    for (int i = 2; i <= nLen; ++i)
    {
        if (nMid > height[i])
        {
            nCnt = 0;
            memset(bVisit, falsesizeof(bVisit));
            continue;
        }
        if (!bVisit[nLoc[sa[i - 1]]])
        {
            bVisit[nLoc[sa[i - 1]]] = true;
            ++nCnt;
        }
        if (!bVisit[nLoc[sa[i]]])
        {
            bVisit[nLoc[sa[i]]] = true;
            ++nCnt;
        }
        if (nCnt == nN) return true;
    }
    
    return false;
}

int main()
{
    int nT;
    
    scanf("%d", &nT);
    while (nT--)
    {
        int nN;
        int nEnd = 300;
        int nP = 0;
        scanf("%d", &nN);
        for (int i = 1; i <= nN; ++i)
        {
            scanf("%s", szStr);
            char* pszStr;
            for (pszStr = szStr; *pszStr; ++pszStr)
            {
                nLoc[nP] = i;
                nNum[nP++] = *pszStr;
            }
            nLoc[nP] = nEnd;
            nNum[nP++] = nEnd++;
            
            reverse(szStr, szStr + strlen(szStr));
            for (pszStr = szStr; *pszStr; ++pszStr)
            {
                nLoc[nP] = i;
                nNum[nP++] = *pszStr;
            }
            nLoc[nP] = nEnd;
            nNum[nP++] = nEnd++;
        }
        nNum[nP] = 0;
        
        da(nNum, nP + 1, nEnd);
        calHeight(nNum, nP);
        
        int nLeft = 1, nRight = strlen(szStr), nMid;
        int nAns = 0;
        while (nLeft <= nRight)
        {
            nMid = (nLeft + nRight) / 2;
            if (Check(nMid, nP, nN))
            {
                nLeft = nMid + 1;
                nAns = nMid;
            }
            else nRight = nMid - 1;
        }
        printf("%d\n", nAns);
    }
    
    return 0;
}


yx 2012-10-23 21:11 发表评论
]]>
poj 3691 DNA repair AC自动?+ dphttp://www.shnenglu.com/csu-yx-2013/archive/2012/10/21/193619.htmlyxyxSun, 21 Oct 2012 08:53:00 GMThttp://www.shnenglu.com/csu-yx-2013/archive/2012/10/21/193619.htmlhttp://www.shnenglu.com/csu-yx-2013/comments/193619.htmlhttp://www.shnenglu.com/csu-yx-2013/archive/2012/10/21/193619.html#Feedback0http://www.shnenglu.com/csu-yx-2013/comments/commentRss/193619.htmlhttp://www.shnenglu.com/csu-yx-2013/services/trackbacks/193619.html可以使文本串不包含Q何一个模式串?br />   q是先徏立Trie图,然后在Trie图上面进行dp。dp的思\也不是很复杂。dp[i][j]的意?br />是长度ؓi的文本串需要改变dp[i][j]个字W顺利到辄态j。需要注意的是长度ؓi的时候,
对应的字W串中的Wi-1个字W。刚开始一直没发现q个bug。而且注意中途不能{Ud
匚w成功的状态上去,多加几个条g控制卛_了。。?br />   转移方程Qdp[i][j] = min(dp[i][j], dp[i-1][nNext] + szText[i-1] != k)Q其中nNext
是从状态j可以转移到的非匹配成功的状态,k代表的当前边的权?br />   
   代码如下Q?br />
#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;

const int MAX_N = 61;
const int MAX_L = 31;
const int MAX_D = 4;
const int INF = 1110;
char chHash[256];
char szPat[MAX_L];

void InitHash()
{
    chHash['A'] = 0;
    chHash['G'] = 1;
    chHash['C'] = 2;
    chHash['T'] = 3;
}

struct Trie
{
    Trie* fail;
    Trie* next[MAX_D];
    bool flag;
    int no;
};
int nP;
Trie* pRoot;
Trie tries[MAX_N * MAX_L];

Trie* NewNode()
{
    memset(&tries[nP], 0, sizeof(Trie));
    tries[nP].no = nP;
    return &tries[nP++];
}

void InitTrie(Trie*& pRoot)
{
    nP = 0;
    pRoot = NewNode();
}

void Insert(Trie* pRoot, char* pszPat)
{
    Trie* pNode = pRoot;
    while (*pszPat)
    {
        int idx = chHash[*pszPat];
        if (pNode->next[idx] == NULL)
        {
            pNode->next[idx] = NewNode();
        }
        pNode = pNode->next[idx];
        ++pszPat;
    }
    pNode->flag = true;
}

void BuildAC(Trie* pRoot)
{
    pRoot->fail = NULL;
    queue<Trie*> qt;
    qt.push(pRoot);

    while (!qt.empty())
    {
        Trie* front = qt.front();
        qt.pop();

        for (int i = 0; i < MAX_D; ++i)
        {
            if (front->next[i])
            {
                Trie* pNode = front->fail;
                while (pNode && pNode->next[i] == NULL)
                {
                    pNode = pNode->fail;
                }
                front->next[i]->fail = pNode? pNode->next[i] : pRoot;
                front->next[i]->flag |= front->next[i]->fail->flag;
                qt.push(front->next[i]);
            }
            else
            {
                front->next[i] = front == pRoot? pRoot : front->fail->next[i];
            }
        }
    }
}

int nChange[INF][INF];
char szText[INF];

int Solve()
{
    int nLen = strlen(szText);
    for (int i = 0; i <= nLen; ++i)
    {
        for (int j = 0; j < nP; ++j)
        {
            nChange[i][j] = INF;
        }
    }

    int i, j, k;
    nChange[0][0] = 0;
    for (i = 1; i <= nLen; ++i)
    {
        for (j = 0; j < nP; ++j)
        {
            if (tries[j].flag) continue;
            if (nChange[i - 1][j] == INF) continue;
            for (k = 0; k < MAX_D; ++k)
            {
                int nNext = tries[j].next[k] - tries;
                if (tries[nNext].flag) continue;
                //trie是边权树,所以i是从1到len,而且当前字符是szText[i-1]
                int nTemp = nChange[i - 1][j] + (k != chHash[szText[i - 1]]);
                nChange[i][nNext] = min(nChange[i][nNext], nTemp);
            }
        }
    }

    int nAns = INF;
    for (i = 0; i < nP; ++i)
    {
        if (!tries[i].flag)
        nAns = min(nAns, nChange[nLen][i]);
    }
    return nAns == INF? -1 : nAns;
}

int main()
{
    int nN;
    int nCase = 1;

    InitHash();
    while (scanf("%d", &nN), nN)
    {
        InitTrie(pRoot);
        while (nN--)
        {
            scanf("%s", szPat);
            Insert(pRoot, szPat);
        }
        BuildAC(pRoot);
        scanf("%s", szText);
        printf("Case %d: %d\n", nCase++, Solve());
    }

    return 0;
}


yx 2012-10-21 16:53 发表评论
]]>
poj 1625 Censored! AC自动?+ DP + 大数加法http://www.shnenglu.com/csu-yx-2013/archive/2012/10/20/193579.htmlyxyxSat, 20 Oct 2012 13:01:00 GMThttp://www.shnenglu.com/csu-yx-2013/archive/2012/10/20/193579.htmlhttp://www.shnenglu.com/csu-yx-2013/comments/193579.htmlhttp://www.shnenglu.com/csu-yx-2013/archive/2012/10/20/193579.html#Feedback0http://www.shnenglu.com/csu-yx-2013/comments/commentRss/193579.htmlhttp://www.shnenglu.com/csu-yx-2013/services/trackbacks/193579.html而且文本串不太长。问题是不取模的话就只能输出实际的答案了Q就只能用大C?br />   而且用大数的话,再用矩阵冥可能就会超时之cȝ?br />   q类题还可以用除矩阵冥外的另外一U解法,是直接dp卛_?br />   二维状态,W一l代表文本串长度Q第二维代表在AC自动Z的状态?br />   比如dp[i][j]代表长度为i的文本串Q{UdTrie图中节点j时候满不包含M模式串的{案?br />剩下的是如何转移状态。{Uȝ话也是考虑next指针数组Q设next = tries[j].next[k]Q?br />那么有dp[i+1][next] = dp[i+1][next] + dp[i][j]Q从0到字母集合大N枚Dk卛_?br />   q个题有一个易错的地方Q就是字母集合可能是ascii码在128?56的范围内。而char
的范围可能是-128?27或??55Q这个是Ҏ~译器不同的。所以,直接用字W串
数组d数据后需要再处理下。可以直接将每个字符?28后再处理?br />   另外Qgetcharq回的是intQ但是与gets之类的函数获得的值的差别也不是那么确定的了?br />我觉得getchar除了对eof之外其余都返回正倹{但是,如果char是有W号的话Qscanf或?br />gets之类得到的char数组里面可能包含负g。。?br />   q个可以生成随机文gQ再用getchardq用%d输出其返回值验证下。验证程序如下:
注释掉的部分是生成随机文件的部分?br />
#include <stdio.h>
#include <stdlib.h>

int main()
{
    char ch;
    freopen("in.txt", "r", stdin);
    //freopen("in.txt", "w", stdout);
    int nNum = 100;
    int nCh;
    do
    {
        printf("%d\n", nCh = getchar());
    }while (nCh != EOF);
    /*while (nNum--)
    {
        putchar(rand() % 256);
    }
*/
    
    return 0;
}
   
   该题的代码如下:
#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;

const int MAX_D = 256;
const int MAX_N = 51;
const int MAX_M = 51;
const int MAX_P = 11;
struct Trie
{
    Trie* fail;
    Trie* next[MAX_D];
    int no;
    bool flag;
};
Trie tries[MAX_P * MAX_P];
int nP;
int nN, nM;
Trie* pRoot;
int nHash[MAX_D];
char szPat[MAX_M];

Trie* NewNode()
{
    memset(&tries[nP], 0, sizeof(Trie));
    tries[nP].no = nP;
    return &tries[nP++];
}

void InitTrie(Trie*& pRoot)
{
    nP = 0;
    pRoot = NewNode();
}

void Insert(Trie* pRoot, char* pszPat)
{
    Trie* pNode = pRoot;
    while (*pszPat)
    {
        int idx = nHash[*pszPat];
        if (pNode->next[idx] == NULL)
        {
            pNode->next[idx] = NewNode();
        }
        pNode = pNode->next[idx];
        ++pszPat;
    }
    pNode->flag = true;
}

void BuildAC(Trie* pRoot)
{
    pRoot->fail = NULL;
    queue<Trie*> qt;
    qt.push(pRoot);
    
    while (!qt.empty())
    {
        Trie* front = qt.front();
        qt.pop();
        
        for (int i = 0; i < nN; ++i)
        {
            if (front->next[i])
            {
                Trie* pNode = front;
                while (pNode && pNode->next[i] == NULL)
                {
                    pNode = pNode->fail;
                }
                front->next[i]->fail = pNode? pNode->next[i] : pRoot;
                front->next[i]->flag |= front->next[i]->fail->flag;
                qt.push(front->next[i]);
            }
            else
            {
                front->next[i] = front->fail->next[i];
            }
        }
    }
}

const int MAX_L = 200;
struct BigInt
{
    int nD[MAX_L];
    BigInt()
    {
        Clear();
    }
    void Clear()
    {
        memset(nD, 0, sizeof(nD));
    }
    
    void Print()
    {
        int i = MAX_L - 1;
        while (!nD[i] && i)--i;
        while (i >= 0)
        {
            putchar(nD[i] + '0');
            --i;
        }
    }
    int operator[](int idx) const
    {
        return nD[idx];
    }
    
    intoperator[](int idx)
    {
        return nD[idx];
    }
};
BigInt bi[MAX_M][MAX_D];

BigInt operator+(const BigInt& one, const BigInt& two)
{
    BigInt ret;
    
    for (int i = 0, nAdd = 0; i < MAX_L; ++i)
    {
        ret[i] = one[i] + two[i] + nAdd;
        nAdd = ret[i] / 10;
        ret[i] %= 10;
    }
    
    return ret;
}

void Solve()
{
    BigInt ans;
    for (int i = 0; i <= nM; ++i)
    {
        for (int j = 0; j < nP; ++j)
        {
            bi[i][j].Clear();
        }
    }
    bi[0][0][0] = 1;
    
    for (int i = 1; i <= nM; ++i)
    {
        for (int j = 0; j < nP; ++j)
        {
            if (tries[j].flag) continue;
            for (int k = 0; k < nN; ++k)
            {
                int nNext = tries[j].next[k] - tries;
                if (tries[nNext].flag == false)
                {
                    bi[i][nNext] = bi[i][nNext] + bi[i - 1][j];
                }
            }
        }
    }
    
    for (int i = 0; i < nP; ++i)
    {
        ans = ans + bi[nM][i];
    }
    ans.Print();
    printf("\n");
}

int main()
{
    int nT;
    
    while (scanf("%d%d%d%*c", &nN, &nM, &nT) == 3)
    {
        int nCh;
        int nTmp = 0;
        memset(nHash, 0, sizeof(nHash));
        while (nCh = getchar(), nCh != '\n')
        {
            if (!nHash[nCh])
            {
                nHash[nCh] = nTmp++;
            }
        }
        InitTrie(pRoot);
        while (nT--)
        {
            gets(szPat);
            Insert(pRoot, szPat);
        }
        printf("1");
        BuildAC(pRoot);
        printf("2");
        Solve();
    }
    
    return 0;
}


yx 2012-10-20 21:01 发表评论
]]>
poj 1509 Glass Beads 字符串最表C?/title><link>http://www.shnenglu.com/csu-yx-2013/archive/2012/10/19/193541.html</link><dc:creator>yx</dc:creator><author>yx</author><pubDate>Fri, 19 Oct 2012 11:44:00 GMT</pubDate><guid>http://www.shnenglu.com/csu-yx-2013/archive/2012/10/19/193541.html</guid><wfw:comment>http://www.shnenglu.com/csu-yx-2013/comments/193541.html</wfw:comment><comments>http://www.shnenglu.com/csu-yx-2013/archive/2012/10/19/193541.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/csu-yx-2013/comments/commentRss/193541.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/csu-yx-2013/services/trackbacks/193541.html</trackback:ping><description><![CDATA[   赤裸裸的字符串最表C题。所谓字W串最表C指的是l定一个字W串Q假讑օ可以循环U?br />位,问@环左Ud位能够得到最的字符丌Ӏ?br />   法x周源的最表C法Q搜索可以找到相兌文和ppt?br />   该算法其实也不是太复杂,思\可以q样理解。假讑֎字符串ؓsQ设s1 = s + s; s2 = s1?br />环左U??现在处理s1和s2Q实际写E序的时候可以通过下标偏移和取模得到s1和s2Q而ƈ不需<br />要生成?br />   处理q程是这LQ设i和j分别指向s1和s2的开头。我们的目的是找到这Li和jQ假设k是s?br />长度Q满x件s1[i,i+k-1] = s2[j,j+k-1] q且s1[i,i+k-1] 是所有满x件的字符串中最的<br />字符Ԍ如果有多个这Ls1[i,i+k-1] 那么我们希望i最?br />   其实q个法主要是做了一个优化,从而把旉搞成U性的。比如,对于当前的i和jQ我们一?br />q行匚wQ也是s1[i,i+k] = s2[j,j+k] 一直满IH然C一个位|s1[i+k]  != s2[j+k]了,<br />现在我们需要改变i和j了。但是,我们不能只是++i或?+j。而是Ҏs1[i+k]>s2[j+k]的话i = <br />i + k + 1Q否则j = j + k + 1。这L瞬移i或者jp够保证复杂度是线性的了?br />   问题是如何证明可以这L瞬移。其实,说穿了也很简单。因为s1[i,i+k - 1] = s2[j,j+k -1]<br />是满的Q只是到了s1[i+k]和s2[j+k]才出现问题了。假如s1[i+k]>s2[j+k]Q那么我们改变i?br />区间[i+1,i+k]中Q何一个值m都不可能得到我们惌的答案,q是因ؓ我们d以在s2中找到相?br />的比s1[m,m+k-1]的字符串s2[j+m-i,j+m-i+k-1]Q因为有s1[i+k]>s2[j+k]?br />   同样对于s1[i+k]<s2[j+k]的情c?br />   文字可能描述的不是很清楚。看PPT能够Ҏ图进行分析?br /><br />   代码如下Q?br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#include <stdio.h><br />#include <stdlib.h><br />#include <<span style="color: #0000FF; ">string</span>.h><br />#include <algorithm><br />#include <<span style="color: #0000FF; ">string</span>><br />#include <iostream><br /><span style="color: #0000FF; ">using</span> <span style="color: #0000FF; ">namespace</span> std;<br /><br /><span style="color: #0000FF; ">int</span> GetMin(<span style="color: #0000FF; ">string</span>& str)<br />{<br />    <span style="color: #0000FF; ">int</span> nSize = str.size();<br />    <span style="color: #0000FF; ">int</span> i = 0, j = 1, k = 0;<br />    <br />    <span style="color: #0000FF; ">while</span> (i < nSize && j < nSize && k < nSize)<br />    {<br />        <span style="color: #0000FF; ">char</span> chDif = str[(i + k) % nSize]<br />                    - str[(j + k) % nSize];<br />        <span style="color: #0000FF; ">if</span> (!chDif) ++k;<br />        <span style="color: #0000FF; ">else</span><br />        {<br />            <span style="color: #0000FF; ">if</span> (chDif > 0) i = i + k + 1;<br />            <span style="color: #0000FF; ">else</span> j = j + k + 1;<br />            <span style="color: #0000FF; ">if</span> (i == j) ++j;<br />            k = 0;<br />        }<br />    }<br />    <span style="color: #0000FF; ">return</span> min(i, j);<br />}<br /><br /><span style="color: #0000FF; ">int</span> main()<br />{<br />    <span style="color: #0000FF; ">string</span> str;<br />    <span style="color: #0000FF; ">int</span> nN;<br />    <br />    scanf("%d", &nN);<br />    <span style="color: #0000FF; ">while</span> (nN--)<br />    {<br />        cin >> str;<br />        printf("%d\n", GetMin(str) + 1);<br />    }<br />    <br />    <span style="color: #0000FF; ">return</span> 0;<br />}</div><img src ="http://www.shnenglu.com/csu-yx-2013/aggbug/193541.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/csu-yx-2013/" target="_blank">yx</a> 2012-10-19 19:44 <a href="http://www.shnenglu.com/csu-yx-2013/archive/2012/10/19/193541.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hnu 2243 考研路茫茫——单词情l?AC自动?矩阵冥篏加和http://www.shnenglu.com/csu-yx-2013/archive/2012/10/18/193489.htmlyxyxThu, 18 Oct 2012 14:02:00 GMThttp://www.shnenglu.com/csu-yx-2013/archive/2012/10/18/193489.htmlhttp://www.shnenglu.com/csu-yx-2013/comments/193489.htmlhttp://www.shnenglu.com/csu-yx-2013/archive/2012/10/18/193489.html#Feedback0http://www.shnenglu.com/csu-yx-2013/comments/commentRss/193489.htmlhttp://www.shnenglu.com/csu-yx-2013/services/trackbacks/193489.html   题意是给定M个模式串Q然后给定长度LQ问不超qL的文本至含有一个模式的情况的ȝ数?br />
   q是用模式串建立Trie图,ҎTrie囑־立v路径长度?的矩阵M?br />   L冉|目ؓ26^1+26^2+...+26^L。不含模式串的情冉|L为矩阵N = M^1+M^2+M^3
+...+M^L的第一行之和。L冉|目减M含模式串的情况就是答案?br />   q里用到了矩늚一些算法,比如快速冥Q还有快速冥求和。但是,我用了操作符重蝲Q最悲剧
的是重蝲后的操作W没有优先Q而我q当作有优先U的在用Q所以悲剧了。。。一直样例都q不
厅R。。唉Q最后才发现了这个问题。。。写?60行左右的代码Q前面的一部分代码可以当作?br />阉|作的模板了。。。Trie囄也不错,q几天估计得打印下来用了。。?br />
   代码如下Q?br />
#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;

typedef unsigned long long INT;
const int MAX_D = 26;
const int MAX_L = 10;
const int MAX_N = 10;
char szPat[MAX_L];

const int MAX_S = 31;
struct Matrix
{
    int nSize;
    INT nD[MAX_S][MAX_S];
    Matrix(int nS)
    {
        Clear(nS);
    }

    Matrix& operator = (const Matrix& m)
    {
        nSize = m.nSize;
        for (int i = 0; i < nSize; ++i)
        {
            for (int j = 0; j < nSize; ++j)
            {
                nD[i][j] = m.nD[i][j];
            }
        }
        return *this;
    }
    void Clear(int nS)
    {
        nSize = nS;
        memset(nD, 0, sizeof(nD));
    }
    void Unit()
    {
        for (int i = 0; i < nSize; ++i)
        {
            for (int j = 0; j < nSize; ++j)
            {
                nD[i][j] = (i == j ? 1 : 0);
            }
        }
    }
};

Matrix operator+(const Matrix& A, const Matrix& B)
{
    Matrix C(A.nSize);

    for (int i = 0; i < A.nSize; ++i)
    {
        for (int j = 0; j < A.nSize; ++j)
        {
            C.nD[i][j] = A.nD[i][j] + B.nD[i][j];
        }
    }
    return C;
}

Matrix operator*(const Matrix& nA, const Matrix& nB)
{
    Matrix nC(nB.nSize);
    for (int i = 0; i < nA.nSize; ++i)
    {
        for (int j = 0; j < nA.nSize; ++j)
        {
            for (int k = 0; k < nA.nSize; ++k)
            {
                nC.nD[i][j] += nA.nD[i][k] * nB.nD[k][j];
            }
        }
    }
    return nC;
}

Matrix operator^(Matrix B, INT nExp)
{
    Matrix ans(B.nSize);

    ans.Unit();
    while (nExp)
    {
        if (nExp % 2)
        {
            ans = ans * B;
        }
        B = B * B;
        nExp >>= 1;
    }
    return ans;
}

//求base^1+base^2++base^N
Matrix SumPowMatrix(Matrix& base, INT nN)
{
    if (nN == 1)
    {
        return base;
    }

    Matrix ans = SumPowMatrix(base, nN / 2);
    ans = ans + ((base^(nN / 2)) * ans);//重蝲q算W保证不了优先
    if (nN % 2)
    {
        ans = ans + (base^nN);//没优先?必须加括?查错2个小时了
    }
    return ans;
}

struct Trie
{
    Trie* next[MAX_D];
    Trie* fail;
    int no;
    bool flag;
};
Trie tries[MAX_L * MAX_N];
int nP;
Trie* pRoot;

Trie* NewNode()
{
    memset(&tries[nP], 0, sizeof(Trie));
    tries[nP].no = nP;
    return &tries[nP++];
}

void InitTrie(Trie*& pRoot)
{
    nP = 0;
    pRoot = NewNode();
}

void Insert(Trie* pRoot, char* pszPat)
{
    Trie* pNode = pRoot;
    while (*pszPat)
    {
        int idx = *pszPat - 'a';
        if (pNode->next[idx] == NULL)
        {
            pNode->next[idx] = NewNode();
        }
        pNode = pNode->next[idx];
        ++pszPat;
    }
    pNode->flag = true;
}

void BuildAC(Trie* pRoot, Matrix& M)
{
    pRoot->fail = NULL;
    queue<Trie*> qt;
    qt.push(pRoot);

    M.Clear(nP);
    while (!qt.empty())
    {
        Trie* front = qt.front();
        qt.pop();
        for (int i = 0; i < MAX_D; ++i)
        {
            if (front->next[i])
            {
                Trie* pNode = front->fail;
                while (pNode && pNode->next[i] == NULL)
                {
                    pNode = pNode->fail;
                }
                front->next[i]->fail = pNode? pNode->next[i] : pRoot;
                if (front->next[i]->fail->flag)
                {
                    front->next[i]->flag = true;
                }
                qt.push(front->next[i]);
            }
            else
            {
                front->next[i] = front == pRoot? pRoot : front->fail->next[i];
            }

            //q里必须要加上front->flag为false的判断么?加不加会生成不同的矩?/span>
            if (!front->next[i]->flag)
            {
                ++M.nD[front->no][front->next[i]->no];
            }
        }
    }
}

int main()
{
    int nN;
    INT nL;
    Matrix M(0);

    while (scanf("%d%I64u", &nN, &nL) == 2)
    {
        InitTrie(pRoot);
        while (nN--)
        {
            scanf("%s", szPat);
            Insert(pRoot, szPat);
        }
        BuildAC(pRoot, M);

        Matrix tmp(1);
        tmp.nD[0][0] = 26;
        tmp = SumPowMatrix(tmp, nL);
        INT nAns = tmp.nD[0][0];
        Matrix msum = SumPowMatrix(M, nL);
        for (int i = 0; i < msum.nSize; ++i)
        {
            nAns -= msum.nD[0][i];
        }
        printf("%I64u\n", nAns);
    }

    return 0;
}


yx 2012-10-18 22:02 发表评论
]]>
poj 2778 DNA Sequence AC自动?矩阵快速冥http://www.shnenglu.com/csu-yx-2013/archive/2012/10/18/193454.htmlyxyxThu, 18 Oct 2012 01:46:00 GMThttp://www.shnenglu.com/csu-yx-2013/archive/2012/10/18/193454.htmlhttp://www.shnenglu.com/csu-yx-2013/comments/193454.htmlhttp://www.shnenglu.com/csu-yx-2013/archive/2012/10/18/193454.html#Feedback0http://www.shnenglu.com/csu-yx-2013/comments/commentRss/193454.htmlhttp://www.shnenglu.com/csu-yx-2013/services/trackbacks/193454.html串的可能性到底有多少U。。?br />   实非常不直观的样子。。?br />   解法是先学学AC自动机,建立起Trie图,Ҏtrie囑֏以得到长度ؓ1的\径矩阵,然后再快?br />冥得到长度ؓN的\径矩c?br />   说v来都非常U结Q没学过AC自动机更加无法理解。学AC自动Z前据说得先学Trie树和KMP
才好理解。学AC自动机搞Trie囑ְp了近2天了Q然后弄懂这个题又是一天,好在基本明白了?br />   马上快比赛了Q从长春换到金华也不知道是好是坏。。。还是弱菜啊。。?br />   贴下我的Trie?快速冥(直接二分?没有写成数论里面那种法)...

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
using namespace std;

typedef long long INT;
const int MOD = 100000;
const int MAX_P = 100;
const int MAX_D = 4;
int nIdx[256];
char szPat[MAX_P];
INT nMatrix[MAX_P][MAX_P];
INT B[MAX_P][MAX_P];
INT A[MAX_P][MAX_P];

void InitIdx()
{
    nIdx['A'] = 0;
    nIdx['C'] = 1;
    nIdx['T'] = 2;
    nIdx['G'] = 3;
}

struct Trie
{
    Trie* fail;
    Trie* next[MAX_D];
    int no;
    bool flag;
    Trie()
    {
        fail = NULL;
        memset(next, 0, sizeof(next));
        no = 0;
        flag = false;
    }
};
Trie tries[MAX_D * MAX_P];
int nP;
Trie* pRoot;

Trie* NewNode()
{
    memset(&tries[nP], 0, sizeof(Trie));
    tries[nP].no = nP;
    return &tries[nP++];
}

void InitTrie(Trie*& pRoot)
{
    nP = 0;
    pRoot = NewNode();
}

void Insert(char* pszPat)
{
    Trie* pNode = pRoot;
    
    while (*pszPat)
    {
        if (pNode->next[nIdx[*pszPat]] == NULL)
        {
            pNode->next[nIdx[*pszPat]] = NewNode();
        }
        pNode = pNode->next[nIdx[*pszPat]];
        ++pszPat;
    }
    pNode->flag = true;
}

int BuildAC(Trie* pRoot)
{
    memset(nMatrix, 0, sizeof(nMatrix));
    
    pRoot->fail = NULL;
    queue<Trie*> qt;
    qt.push(pRoot);
    while (!qt.empty())
    {
        Trie* front = qt.front();
        qt.pop();
        
        for (int i = 0; i < MAX_D; ++i)
        {
            if (front->next[i])
            {
                Trie* pNode = front->fail;
                while (pNode && pNode->next[i] == NULL)
                {
                    pNode = pNode->fail;
                }
                front->next[i]->fail = pNode? pNode->next[i] : pRoot;
                if (front->next[i]->fail->flag == true)
                {
                    front->next[i]->flag = true;
                }
                
                qt.push(front->next[i]);
            }
            else
            {
                front->next[i] = front == pRoot? pRoot : front->fail->next[i];
            }
            
            if (front->next[i]->flag == false)
            {
                nMatrix[front->no][front->next[i]->no]++;
            }
        }
    }
    
    return nP;//节点M?/span>
}

void MultyMatrix(INT A[][MAX_P], INT B[][MAX_P], INT C[][MAX_P], int nSize)
{
    for (int i = 0; i < nSize; ++i)
    {
        for (int j = 0; j < nSize; ++j)
        {
            INT nSum = 0;
            for (int k = 0; k < nSize; ++k)
            {
                nSum = (nSum + A[i][k] * B[k][j]) % MOD;
            }
            C[i][j] = nSum;
        }
    }
}

void CopyMatrix(INT A[][MAX_P], INT B[][MAX_P], int nSize)
{
    for (int i = 0; i < nSize; ++i)
    {
        for (int j = 0; j < nSize; ++j)
        {
            A[i][j] = B[i][j];
        }
    }
}

void MatrixPower(INT M[][MAX_P], int nSize, INT nP)
{
    if (nP == 1)
    {
        CopyMatrix(A, M, nSize);
        return;
    }
    
    MatrixPower(M, nSize, nP / 2);
    MultyMatrix(A, A, B, nSize);
    if (nP % 2)
    {
        MultyMatrix(B, M, A, nSize);
    }
    else
    {
        CopyMatrix(A, B, nSize);
    }
}

int main()
{
    INT nM, nN;
    
    InitIdx();
    while (scanf("%I64d%I64d", &nM, &nN) == 2)
    {
        InitTrie(pRoot);
        while (nM--)
        {
            scanf("%s", szPat);
            Insert(szPat);
        }
        int nSize = BuildAC(pRoot);
        
        MatrixPower(nMatrix, nSize, nN);
        INT nAns = 0;
        for (int i = 0; i < nSize; ++i)
        {
            nAns = (nAns + A[0][i]) % MOD;
        }
        printf("%I64d\n", nAns % MOD);
    }
    
    return 0;
}
   
   

yx 2012-10-18 09:46 发表评论
]]>
hnu 10076 Jimmy's Riddles DFAhttp://www.shnenglu.com/csu-yx-2013/archive/2012/10/12/193227.htmlyxyxFri, 12 Oct 2012 14:14:00 GMThttp://www.shnenglu.com/csu-yx-2013/archive/2012/10/12/193227.htmlhttp://www.shnenglu.com/csu-yx-2013/comments/193227.htmlhttp://www.shnenglu.com/csu-yx-2013/archive/2012/10/12/193227.html#Feedback2http://www.shnenglu.com/csu-yx-2013/comments/commentRss/193227.htmlhttp://www.shnenglu.com/csu-yx-2013/services/trackbacks/193227.html   感觉用dfa只需要保证状态{换图对了Q基本上׃会出bug了,但是其它的方法去匚w
q种cM正则表达式的字符串就Ҏ出错多了?br />
   癑ֺ癄的DFA定义如下Q?br />      英文全称QDeterministic Finite Automaton, 写:DFA
  DFA定义Q一个确定的有穷自动机(DFAQM是一个五元组QM=QKQ?#931;QfQSQZQ其?br />  ① K是一个有I集Q它的每个元素称Z个状态;
  ② Σ是一个有I字母表Q它的每个元素称Z个输入符P所以也U?#931;入符号字母表Q?br />  ③ f是{换函敎ͼ是K×Σ→K上的映射Q即Q如 fQkiQaQ?kjQ(ki∈KQkj∈KQ就意味着Q?br />当前状态ؓkiQ输入符为aӞ{换ؓ下一个状态kjQ我们把kjUCki的一个后l状态;
  ④ S ∈ K是唯一的一个初态;
  ⑤ Z⊂K是一个终态集Q终态也U可接受状态或l束状态?/span>

   该题的状态{换图Q?br />   
   现在再根据状态{换图Q写一个模拟{换关pȝ匚w非常方便了。。?br />   代码如下Q?br />
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>
using namespace std;

string strNouns[8] =
{
    "tom", "jerry", "goofy", "mickey",
    "jimmy", "dog", "cat", "mouse"
};

bool IsNoun(string& str)
{
    for (int i = 0; i < 8; ++i)
    {
        if (str == strNouns[i])
        {
            return true;
        }
    }
    return false;
}

bool IsVerb(string& str)
{
    return str == "hate" || str == "love"
            || str == "know" || str == "like"
            || str == "hates" || str == "loves"
            || str == "knows" || str == "likes"; 
}

bool IsArticle(string& str)
{
    return str == "a" || str == "the";
}

bool CheckState(vector<string>& vs)
{
    if (vs.empty()) return false;
    
    int nState = 0;
    for (int i = 0; i < vs.size(); ++i)
    {
        //printf("nState:%d, str:%s\n", nState, vs[i].c_str());
        switch (nState)
        {
            case 0:
                if (IsArticle(vs[i]))
                {
                    nState = 1;
                    break;
                }
                else if (IsNoun(vs[i]))
                {
                    nState = 2;
                    break;
                }
                else
                {
                    return false;
                }
                
            case 1:
                if (IsNoun(vs[i]))
                {
                    nState = 2;
                    break;
                }
                else
                {
                    return false;
                }
                
            case 2:
                if (vs[i] == "and")
                {
                    nState = 0;
                    break;
                }
                else if (IsVerb(vs[i]))
                {
                    nState = 3;
                    break;
                }
                else
                {
                    return false;
                }
                
            case 3:
                if (IsArticle(vs[i]))
                {
                    nState = 4;
                    break;
                }
                else if (IsNoun(vs[i]))
                {
                    nState = 5;
                    break;
                }
                else
                {
                    return false;
                }
                
            case 4:
                if (IsNoun(vs[i]))
                {
                    nState = 5;
                    break;
                }
                else
                {
                    return false;
                }
                
            case 5:
                if (vs[i] == "and")
                {
                    nState = 3;
                    break;
                }
                else if (vs[i] == ",")
                {
                    nState = 0;
                    break;
                }
                else
                {
                    return false;
                }
        }
    }
    
    return nState == 5;
}

int main()
{
    int nT;
    
    scanf("%d%*c", &nT);
    while (nT--)
    {
        vector<string> vs;
        string line, str;
        
        getline(cin, line);
        stringstream ss(line);
        while (ss >> str)
        {
            vs.push_back(str);
        }
        printf("%s\n", CheckState(vs) ? "YES I WILL" : "NO I WON'T");
    }
    
    return 0;
}


yx 2012-10-12 22:14 发表评论
]]>
poj 2406 Power Strings kmp的妙?/title><link>http://www.shnenglu.com/csu-yx-2013/archive/2012/09/30/192497.html</link><dc:creator>yx</dc:creator><author>yx</author><pubDate>Sun, 30 Sep 2012 07:25:00 GMT</pubDate><guid>http://www.shnenglu.com/csu-yx-2013/archive/2012/09/30/192497.html</guid><wfw:comment>http://www.shnenglu.com/csu-yx-2013/comments/192497.html</wfw:comment><comments>http://www.shnenglu.com/csu-yx-2013/archive/2012/09/30/192497.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.shnenglu.com/csu-yx-2013/comments/commentRss/192497.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/csu-yx-2013/services/trackbacks/192497.html</trackback:ping><description><![CDATA[   q个题是求一个字W串的最重复单元的重复ơ数Q那么求出最重复单元的长度卛_?br />   q个题有3U方法,Ҏ一Q直接枚N度ؓ[1,len/2]内的子串Q暴力就q了。方法二Q?br />原串重复一ơŞ成一个新Ԍ用原串去匚wCQ但是得从第二个位置开始匹配,W一?br />成功匚w的位|减一׃表最重复单元的长度。方法三Q利用kmp的next函数Q如果len<br />能够整除len-next[len]Q那么len-next[len]׃表最重复单元的长度?br />   Ҏ一明显是对的,数据不强的情况下p水过了。方法二也不是那么容易想到的Q不q?br />原串扩展ؓ2倍的做法也不是太奇葩Q比如判?个@环串是否相等可以用q个办法做?br />Ҏ三就比较隄解了?br />   Ҏ三的理解Q?br />   next[len]代表的是str的最长前~(使得q个前缀与同样长度的后缀相等)的长度。所谓的next<br />数组是长度?-len的str的满上q描q的最长前~的长度。如果len是len-next[len]的倍数Q?br />假设m = len-next[len] Q那么str[1-m] = str[m-2*m]Q以此类推下去,m肯定是str的最?br />重复单元的长度。假如len不是len-next[len]的倍数Q?如果前缀和后~重叠Q那么最重复单?br />肯定str本n了,如果前缀和后~不重叠,那么str[m-2*m] != str[len-m,len]Q所以str[1-m]<br />!= str[m-2*m] ,最l肯定可以推理出最重复单元是str本nQ因为只要不断递增m证明卛_?br />   <br />   Ҏ三的代码如下Q?br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#include <stdio.h><br />#include <<span style="color: #0000FF; ">string</span>.h><br />#include <algorithm><br /><span style="color: #0000FF; ">using</span> <span style="color: #0000FF; ">namespace</span> std;<br /><br /><span style="color: #0000FF; ">char</span> szStr[1000010];<br /><span style="color: #0000FF; ">int</span> nNext[1000010];<br /><br /><span style="color: #0000FF; ">void</span> GetNext(<span style="color: #0000FF; ">char</span>* szStr, <span style="color: #0000FF; ">int</span> nLen, <span style="color: #0000FF; ">int</span>* nNext)<br />{<br />    nNext[0] = -1;<br />    <span style="color: #0000FF; ">for</span> (<span style="color: #0000FF; ">int</span> i = 1, j = -1; i < nLen; ++i)<br />    {<br />        <span style="color: #0000FF; ">while</span> (j > -1 && szStr[i] != szStr[j + 1])<br />        {<br />            j = nNext[j];<br />        }<br />        <span style="color: #0000FF; ">if</span> (szStr[i] == szStr[j + 1])<br />        {<br />            ++j;<br />        }<br />        nNext[i] = j;<br />    }<br />}<br /><br /><span style="color: #0000FF; ">int</span> main()<br />{<br />    <span style="color: #0000FF; ">while</span> (scanf("%s", szStr), strcmp(szStr, "."))<br />    {<br />        <span style="color: #0000FF; ">int</span> nLen = strlen(szStr);<br />        <br />        GetNext(szStr, nLen, nNext);<br />        <span style="color: #0000FF; ">if</span> (nLen % (nLen - nNext[nLen - 1] - 1))<br />        {<br />            printf("1\n");<br />        }<br />        <span style="color: #0000FF; ">else</span><br />        {<br />            printf("%d\n", nLen / (nLen - nNext[nLen - 1] - 1));<br />        }<br />    }<br />    <br />    <span style="color: #0000FF; ">return</span> 0;<br />}</div><br />   <br />   <img src ="http://www.shnenglu.com/csu-yx-2013/aggbug/192497.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/csu-yx-2013/" target="_blank">yx</a> 2012-09-30 15:25 <a href="http://www.shnenglu.com/csu-yx-2013/archive/2012/09/30/192497.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>poj 3461 Oulipo Rabin-Karp 字符串匹?/title><link>http://www.shnenglu.com/csu-yx-2013/archive/2012/09/28/192234.html</link><dc:creator>yx</dc:creator><author>yx</author><pubDate>Fri, 28 Sep 2012 04:01:00 GMT</pubDate><guid>http://www.shnenglu.com/csu-yx-2013/archive/2012/09/28/192234.html</guid><wfw:comment>http://www.shnenglu.com/csu-yx-2013/comments/192234.html</wfw:comment><comments>http://www.shnenglu.com/csu-yx-2013/archive/2012/09/28/192234.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/csu-yx-2013/comments/commentRss/192234.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/csu-yx-2013/services/trackbacks/192234.html</trackback:ping><description><![CDATA[   裸的字符串匹配,子串最?0,000Q母串最?span style="font-family: 'Times New Roman', Times, serif; font-size: 16px; line-height: normal; ">1,000,000?br /></span>   求子串在母串中出现的ơ数?br />   如果子串长度较小Q那么直接RK匚w卛_Qhash值相同时候,直接比较字符串是否相同?br />但是q个题的子串太长了,q比较字W串会超Ӟ如果不比较字W串理论上是错误的,虽然<br />出错的概率很,而且概率q是跟模数的选择以及q算时候是否溢出有兟?br />   刚开始用了intQ发C直wa了,估计是q算时候就int了,取模没vC用。模数的?br />择能够提高正率。Rabin-Karp 字符串匹配虽然比较好写,也很Ҏ理解Q但是适用情况?br />觉不是很q,比如子串太长了,处理麻烦了Q舍弃子串比较也不是很好?br />   但是子串不长的话QRabin-Karp 字符串匹配还是很不错的?br />   相比而言Q这个题用kmp应该会好很多?br /><br />   代码如下Q?br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all">#include <stdio.h> <br />#include <<span style="color: #0000FF; ">string</span>.h><br />#include <algorithm><br /><span style="color: #0000FF; ">using</span> <span style="color: #0000FF; ">namespace</span> std;<br /><br />typedef <span style="color: #0000FF; ">long</span> <span style="color: #0000FF; ">long</span> INT;<br /><span style="color: #0000FF; ">char</span> szStrM[1000010];<br /><span style="color: #0000FF; ">char</span> szStrS[10010];<br /><span style="color: #0000FF; ">const</span> INT MOD = 16381 * 4733 + 1;<br /><br /><span style="color: #0000FF; ">int</span> main()<br />{<br />    <span style="color: #0000FF; ">int</span> nT;<br />    <br />    scanf("%d", &nT);<br />    <span style="color: #0000FF; ">while</span> (nT--)<br />    {<br />        scanf("%s%s", szStrS, szStrM);<br />        INT nMatch = szStrS[0] - 'A';<br />        INT nPowN = 1;<br />        <span style="color: #0000FF; ">int</span> nSizeS = 1;<br />        <span style="color: #0000FF; ">char</span>* pszStr = szStrS + 1;<br />        <span style="color: #0000FF; ">while</span> (*pszStr)<br />        {<br />            nMatch = (26 * nMatch + *pszStr - 'A') % MOD;<br />            nPowN = (nPowN * 26) % MOD;<br />            ++nSizeS;<br />            ++pszStr;<br />        }<br />        <span style="color: #008000; ">//</span><span style="color: #008000; ">prINTf("match:%d\n", nMatch);</span><span style="color: #008000; "><br /></span>        <br />        <span style="color: #0000FF; ">int</span> nSizeM = strlen(szStrM);<br />        INT nKey = 0;<br />        <span style="color: #0000FF; ">for</span> (<span style="color: #0000FF; ">int</span> i = 0; i < nSizeS; ++i)<br />        {<br />            nKey = (26 * nKey + szStrM[i] - 'A') % MOD;<br />        }<br />        <span style="color: #008000; ">//</span><span style="color: #008000; ">prINTf("key:%d\n", nKey);</span><span style="color: #008000; "><br /></span>        <br />        <span style="color: #0000FF; ">int</span> nAns = 0;<br />        <span style="color: #0000FF; ">for</span> (<span style="color: #0000FF; ">int</span> i = 0; i <= nSizeM - nSizeS; ++i)<br />        {<br />            <span style="color: #008000; ">//</span><span style="color: #008000; ">prINTf("key:%d\n", nKey);</span><span style="color: #008000; "><br /></span>            <span style="color: #0000FF; ">if</span> (nKey == nMatch)<br />               <span style="color: #008000; ">//</span><span style="color: #008000; "> && memcpy(szStrS, szStrM + i, nSizeS) == 0)</span><span style="color: #008000; "><br /></span>            {<br />                ++nAns;<br />            }<br />            nKey = (26 * (nKey - nPowN * (szStrM[i] - 'A')) % MOD<br />                    + szStrM[i + nSizeS] - 'A') % MOD;<br />            nKey = (nKey + MOD) % MOD;<br />        }<br />        <br />        printf("%d\n", nAns);<br />    }<br />    <br />    <span style="color: #0000FF; ">return</span> 0;<br />}</div><img src ="http://www.shnenglu.com/csu-yx-2013/aggbug/192234.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/csu-yx-2013/" target="_blank">yx</a> 2012-09-28 12:01 <a href="http://www.shnenglu.com/csu-yx-2013/archive/2012/09/28/192234.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>poj 1200 Crazy Search 字符串hash http://www.shnenglu.com/csu-yx-2013/archive/2012/09/27/192186.htmlyxyxThu, 27 Sep 2012 14:07:00 GMThttp://www.shnenglu.com/csu-yx-2013/archive/2012/09/27/192186.htmlhttp://www.shnenglu.com/csu-yx-2013/comments/192186.htmlhttp://www.shnenglu.com/csu-yx-2013/archive/2012/09/27/192186.html#Feedback0http://www.shnenglu.com/csu-yx-2013/comments/commentRss/192186.htmlhttp://www.shnenglu.com/csu-yx-2013/services/trackbacks/192186.html的个数NC?br />   保存子串到set里面直接暴力肯定时了。这个题有个利用字符串hash的解法,虽然理论上有
bugQ但是能q这个题?br />   利用l出的NCQ对长度为N的字W串Q将其当作NCq制的数字,求出其|对D行hashQ?br />求出不同的hash位置个数?br />   q个法其实cM于Karp-Rabin字符串匹配算法。不q,Karp-Rabin法做了Ҏq,?br />q制为D的字W串求值的时候ؓ了防止溢Z模一个素敎ͼ而且不会每次都P代求下一个子串的
|而是从当前子串的值直接递推Z一个字W的倹{怎么递推了,其实很简单,是当前值去
掉最高位再乘以D(相当于左UM?不过是Dq制的,不能直接?lt;<W号)Q再加上新的最低位?br />   Karp-Rabin法应该主要在于设计出合理的hash法Q比如,用取模hash函数的话Q得?br />证hash表够大Q否则冲H太多,速度׃会怎么好了。比如这个题Qhash表小了就AC不了了?br />
   代码如下Q?br />
#include <stdio.h>
#include <string.h>

const int MAX = 13747347;
int nHash[MAX];
char szStr[17000001];
int nN, nNC;
int nW[200];

void Insert(int nKey)
{
    int nPos = nKey;
    while (nHash[nPos] != -1 && nHash[nPos] != nKey)
    {
        nPos = (nPos + 1) % MAX;
    }
    nHash[nPos] = nKey;
}

bool Find(int nKey)
{
    int nPos = nKey;
    while (nHash[nPos] != -1 && nHash[nPos] != nKey)
    {
        nPos = (nPos + 1) % MAX;
    }
    return nHash[nPos] != -1;
}

int main()
{
    while (scanf("%d%d%s", &nN, &nNC, szStr) == 3)
    {
        memset(nW, 0, sizeof(nW));
        memset(nHash, -1, sizeof(nHash));
        int nNum = 0;
        int nSize = 0;
        for (char* pszStr = szStr; *pszStr; ++pszStr)
        {
            if (!nW[*pszStr])
            {
                nW[*pszStr] = ++nNum;
            }
            ++nSize;
        }

        int nKey = 0;
        int nAns = 0;
        int nPowN = 1;
        for (int j = 0; j < nN; ++j)
        {
            nKey = (nKey * nNC + nW[szStr[j]]) % MAX;
            nPowN *= nNC;
        }
        nPowN /= nNC;
        if (!Find(nKey))
        {
            Insert(nKey);
            nAns++;
        }
        
        for (int i = nN; i < nSize; ++i)
        {
            nKey = (nNC * (nKey - nPowN * nW[szStr[i - nN]])
                    + nW[szStr[i]]) % MAX;
            nKey = (nKey + MAX) % MAX;
            
            if (!Find(nKey))
            {
                Insert(nKey);
                nAns++;
            }
        }
        
        printf("%d\n", nAns);
    }

    return 0;
}


yx 2012-09-27 22:07 发表评论
]]>
Uva 465 - Overflowhttp://www.shnenglu.com/csu-yx-2013/archive/2012/04/03/169936.htmlyxyxTue, 03 Apr 2012 09:11:00 GMThttp://www.shnenglu.com/csu-yx-2013/archive/2012/04/03/169936.htmlhttp://www.shnenglu.com/csu-yx-2013/comments/169936.htmlhttp://www.shnenglu.com/csu-yx-2013/archive/2012/04/03/169936.html#Feedback2http://www.shnenglu.com/csu-yx-2013/comments/commentRss/169936.htmlhttp://www.shnenglu.com/csu-yx-2013/services/trackbacks/169936.html   q种题我一直忘记忽略前?0'?br />   q有题目没有l出最长的数字的长度,所以最好用stringcR?br />   使用longlong之前最好已l测试了OJQ是?lldq是%I64dQ如果OJ后台是linux下的g++Q只能是%lldQWindows下的MinGW32
(Dev-C++也一L的是q个?要用%I64d才能正确。所以预赛之前需要对普通题q行试下?br />   q有注意复合逻辑表达式是否写正确了,最q经常写错了Q太郁闷了?br />   l自己提个醒吧,校赛q种题再不能q速A掉基本太丢h了?br />
   代码如下Q?br />
#include <stdio.h> 
#include <limits.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define MAX (10000)
char szIntMax[20];
char szLine[MAX];
char szOne[MAX];
char szTwo[MAX];
char szOper[10];

char* MyItoa(int nNum, char* pszNum, int nBase)
{
    int nLen = 0;
    while (nNum)
    {
        pszNum[nLen++] = nNum % nBase + '0';
        nNum /= nBase;
    }
    reverse(pszNum, pszNum + nLen);
    pszNum[nLen] = '\0';
    
    return pszNum;
}

bool IsBigger(char* pszOne, int nLenOne, char* pszTwo, int nLenTwo)
{
    //printf("pszOne:%s, pszTwo:%s\n", pszOne, pszTwo);
    if (nLenOne != nLenTwo)
    {
        return nLenOne > nLenTwo;
    }
    else
    {
        for (int i = 0; i < nLenOne; ++i)
        {
            if (pszOne[i] != pszTwo[i])
            {
                return pszOne[i] > pszTwo[i];
            }
        }
        return false;
    }
}

int StripHeadZero(char* pszNum)
{
    int nLen = strlen(pszNum);
    int i;
    
    for (i = 0; i < nLen && pszNum[i] == '0'; ++i);
    if (i == nLen)
    {
        pszNum[0] = '0';
        pszNum[1] = '\0';
        nLen = 2;
    }
    else
    {
        char* pszWrite = pszNum;
        char* pszRead = pszNum + i;
        nLen = 0;
        while (*pszRead)
        {
            *pszWrite++ = *pszRead++;
            ++nLen;
        }
        *pszWrite = '\0';
    }
    
    return nLen;
}

int main()
{
    int nIntMax = INT_MAX;
    MyItoa(nIntMax, szIntMax, 10);
    int nLenMax = strlen(szIntMax);
    
    while (gets(szLine))
    {
        if (szLine[0] == '\0')
        {
            continue;
        }
        
        sscanf(szLine, "%s%s%s", szOne, szOper, szTwo);
        printf("%s %s %s\n", szOne, szOper, szTwo);
        StripHeadZero(szOne);
        StripHeadZero(szTwo);
        
        int nLenOne = strlen(szOne);
        int nLenTwo = strlen(szTwo);
        bool bFirst = false;
        bool bSecond = false;
        
        if (IsBigger(szOne, nLenOne, szIntMax, nLenMax))
        {
            printf("first number too big\n");
            bFirst = true;
        }
        
        if (IsBigger(szTwo, nLenTwo, szIntMax, nLenMax))
        {
            printf("second number too big\n");
            bSecond = true;
        }
        
        if (bFirst || bSecond)
        {
            if (szOper[0] == '+' || (szOper[0] == '*' && szOne[0] != '0' && szTwo[0] != '0'))
            {
                printf("result too big\n");
            }
        }
        else
        {
            long long nOne, nTwo;
            sscanf(szLine, "%lld%s%lld", &nOne, szOper, &nTwo);
            long long nResult;

            if (szOper[0] == '+')
            {
                nResult = nOne + nTwo;
            }
            else if (szOper[0] == '*')
            {
                nResult = nOne * nTwo;
            }
            //printf("%I64d\n", nResult);
            if (nResult > INT_MAX)
            {
                printf("result too big\n");
            }
        }
    }
    
    return 0;
}


yx 2012-04-03 17:11 发表评论
]]>
hdu - 1225:Football Scorehttp://www.shnenglu.com/csu-yx-2013/archive/2012/03/14/167916.htmlyxyxWed, 14 Mar 2012 13:23:00 GMThttp://www.shnenglu.com/csu-yx-2013/archive/2012/03/14/167916.htmlhttp://www.shnenglu.com/csu-yx-2013/comments/167916.htmlhttp://www.shnenglu.com/csu-yx-2013/archive/2012/03/14/167916.html#Feedback2http://www.shnenglu.com/csu-yx-2013/comments/commentRss/167916.htmlhttp://www.shnenglu.com/csu-yx-2013/services/trackbacks/167916.html再二分很ȝQ速度也快不了多少Q因为只是输入的q程中需要查找。但是,q个题其实很好用map做,代码量可以少很多Q也很简z?br />   写这blog的目的是Z提醒自己Q容易题再这样错下去Q真的很伤h心,学什么都没必要了Q当时打l搞ACM的目的之一是
Z提高代码正确率。这个题Q不仅细节部分没看清楚,而且写代码时候把比较函数里面的one.nLost写成了one.nGetQ查错了1个多
时Q还让队友帮忙查错了好久Q真的很无语。写E序实可以debugQ但是这也让我养成了很严重的依赖debug的习惯?br />   人生不可以debugQh生不可以重来。记得以前很多次很多事情是开始无所谓,后面悲催到底Q无限后悔?br />
   代码如下Q?br />   1 #include <stdio.h>
  2 #include <string.h>
  3 #include <string>
  4 #include <map>
  5 #include <vector>
  6 #include <algorithm>
  7 #define MAX (100)
  8 using std::map;
  9 using std::string;
 10 using std::vector;
 11 using std::sort;
 12 
 13 struct INFO
 14 {
 15     INFO()
 16     {
 17         nScore = nGet = nLost = 0;
 18     }
 19 
 20     string strName;
 21     int nScore;
 22     int nGet;
 23     int nLost;
 24     bool operator < (const INFO& one) const
 25     {
 26         if (nScore != one.nScore)
 27         {
 28             return nScore > one.nScore;
 29         }
 30         else if (nGet - nLost != one.nGet - one.nLost)//q里把one.nLost写成了one.nGet
 31         {
 32             return nGet - nLost > one.nGet - one.nLost;
 33         }
 34         else if (nGet != one.nGet)
 35         {
 36             return nGet > one.nGet;
 37         }
 38         else
 39         {
 40             return strName < one.strName;
 41         }
 42     }
 43 };
 44 
 45 int main()
 46 {
 47     int nN;
 48 
 49     //freopen("in.txt", "r", stdin);
 50     //freopen("out.txt", "w", stdout);
 51     while (scanf("%d", &nN) == 1)
 52     {
 53         int nLast = nN * (nN - 1);
 54         char szOne[MAX];
 55         char szTwo[MAX];
 56         int nOne, nTwo;
 57 
 58         map<string, INFO> myMap;
 59         for (int i = 0; i < nLast; ++i)
 60         {
 61             scanf("%s %*s %s %d:%d", szOne, szTwo, &nOne, &nTwo);
 62             //printf("%s %s %d %d\n", szOne, szTwo, nOne, nTwo);
 63             
 64             string strOne = szOne;
 65             myMap[strOne].strName = strOne;
 66             myMap[strOne].nGet += nOne;
 67             myMap[strOne].nLost += nTwo;
 68             
 69             string strTwo = szTwo;
 70             myMap[strTwo].strName = strTwo;
 71             myMap[strTwo].nGet += nTwo;
 72             myMap[strTwo].nLost += nOne;
 73 
 74             if (nOne > nTwo)
 75             {
 76                 myMap[strOne].nScore += 3;
 77             }
 78             else if (nOne == nTwo)
 79             {
 80                 myMap[strOne].nScore += 1;
 81                 myMap[strTwo].nScore += 1;
 82             }
 83             else
 84             {
 85                 myMap[strTwo].nScore += 3;
 86             }
 87         }
 88         
 89         map<string, INFO>::iterator it;
 90         vector<INFO> myVt;
 91         for (it = myMap.begin(); it != myMap.end(); it++)
 92         {
 93             myVt.push_back(it->second);
 94         }
 95         
 96         sort(myVt.begin(), myVt.end());
 97         for (int i = 0; i < myVt.size(); ++i)
 98         {
 99             printf("%s %d\n", myVt[i].strName.c_str(), myVt[i].nScore);
100         }
101         printf("\n");
102     }
103     
104     return 0;
105 }


yx 2012-03-14 21:23 发表评论
]]>
POJ癄 - 2818:密码http://www.shnenglu.com/csu-yx-2013/archive/2011/11/10/159934.htmlyxyxThu, 10 Nov 2011 12:56:00 GMThttp://www.shnenglu.com/csu-yx-2013/archive/2011/11/10/159934.htmlhttp://www.shnenglu.com/csu-yx-2013/comments/159934.htmlhttp://www.shnenglu.com/csu-yx-2013/archive/2011/11/10/159934.html#Feedback4http://www.shnenglu.com/csu-yx-2013/comments/commentRss/159934.htmlhttp://www.shnenglu.com/csu-yx-2013/services/trackbacks/159934.htmlhttp://poj.grids.cn/practice/2818
q其实就是一个简单的UM密码法?只是多了个@环而已,密码学里面也指出q@环运是没有效果?所以题目估计也p察了这一?如果没有扑և循环周期,此题会一直超时的...
刚开?我就直接模拟Kơ加?昄时?当时q不信了,以ؓ单至此。。?br />后面我就开始改q了,刚开始是把周期计和加密攑֜一起写?样例也过?但是q是一直错...
没办法再?我改成把周期求出?再对加密ơ数K取模?再进行运?..
好吧,q是一样wa,后面变成PE了。。?br />最?q个题经q我q?个小时的奋战,l于q了,一共错了近10ơ吧...W一ơ提交是距现?个多时前了...
最后发现错误的原因q是换行输出的地斚w?题目要求是每一l中间有个空?我则输出的是每次计算后有个空?..
实在无语...
思维不严谨啊...

代码:
#include <stdio.h>
#include <string.h>
#define N_MAX 200 + 10
int main()
{
    int nN = 0;
    int nNArr[N_MAX];//密钥
    int nK = 0;
    char szMsg[N_MAX];
    char szMsgBckup[N_MAX];//字符串备?/div>
    int nCir[N_MAX];//周期
    int nMsgLen = 0;
    int nPos = 0;
    int i, j;
    
    while (scanf("%d", &nN), nN != 0)
    {
        for (i = 1; i <= nN; ++i)
        {
            scanf("%d", &nNArr[i]);
        }
        
        for (i = 1; i <= nN; ++i)//计算周期
        {
            nPos = i;
            for (j = 1; ; ++j)
            {
                nPos = nNArr[nPos];
                if (nPos == i)
                {
                    nCir[i] = j;
                    break;
                }
            }
        }
        
        while (scanf("%d", &nK), nK != 0)
        {
            getchar();//销掉空?/div>
            gets(szMsg + 1);
            nMsgLen = strlen(szMsg + 1);
            for (i = nMsgLen; i < nN; ++i)
            {
                szMsg[1 + i] = ' ';
            }
            szMsg[1 + nN] = '\0';
            strcpy(szMsgBckup + 1, szMsg + 1);
            
            for (i = 1; i <= nN; ++i)
            {
                nPos = i;
                int nTimes = nK % nCir[i];
                for (j = 1; j <= nTimes; ++j)
                {
                    nPos = nNArr[nPos];
                }
                szMsg[nPos] = szMsgBckup[i];
            }
            
            printf("%s\n", szMsg + 1);
        }
        printf("\n");
    }
    
    return 0;
}


yx 2011-11-10 20:56 发表评论
]]> ˾þۺϳ| ѾþþƷѾѾ| 97þóƷɰ| һþöAV| 99þù޸ۿ2024 | þþƷav鶹ͼƬ| 91Ʒ91þþþþ| þۺϾþԾ99ëƬ| ݺݾƷþþĻ| ֻоƷþ| þþƷ| 99þùۺϾƷŮͬͼƬ| Ʒþþþ9999| ѾþþƷ99reѾy| ޾ƷۺϾþ| AVþþþòվ | ˮϵþþƷ| ĻhdþþƷ| 볬鱬Ļþ| ɫۺϾþʮ·| 󽶾þĻ| þһ | ˾þ| ŷ߽˾þ| þ޹Ʒ123| ˾þô߽槼| AVպƷþþþ| ɫۺϾþ| Ʒ99þþþ91gav| þùƷӰԺ| Ʒݾþþþø| ۺϾþþƷɫ| þۺ77777| ƷѾþþþþþþ| þùƷþþ| þAV| ޷AVþò| ɫþþۺ| ݺɫþۺѿ| ۿ ۺϾþþþùɫ ŷ һ | 88þþƷһëƬ|