1 回答

TA貢獻(xiàn)1828條經(jīng)驗(yàn) 獲得超3個(gè)贊
問(wèn)題來(lái)源
在經(jīng)歷了持續(xù)兩天三夜的光榮戰(zhàn)斗(以及來(lái)自評(píng)論的驚人想法和想法)之后,我終于設(shè)法解決了這個(gè)問(wèn)題!
我想為遇到類(lèi)似問(wèn)題的任何人發(fā)布一個(gè)答案,其中該string.Substring(i, j)函數(shù)不是獲取字符串子字符串的可接受解決方案,因?yàn)樽址蟛⑶夷鸁o(wú)法負(fù)擔(dān)string.Substring(i, j)(它必須制作一個(gè)副本,因?yàn)?C# 字符串是不可變的,無(wú)法繞過(guò)它)或者在string.Substring(i, j)同一個(gè)字符串上被大量調(diào)用(就像在我的嵌套 for 循環(huán)中)給垃圾收集器帶來(lái)了困難,或者就像我的情況一樣!
嘗試
我已經(jīng)嘗試了許多建議的東西,例如StringBuilder、Streams、在塊內(nèi)使用Intptr和Marshal 的非托管內(nèi)存分配unsafe{},甚至創(chuàng)建一個(gè) IEnumerable 并通過(guò)引用返回給定位置內(nèi)的字符。所有這些嘗試最終都失敗了,因?yàn)楸仨毻瓿赡撤N形式的數(shù)據(jù)連接,因?yàn)槲覜](méi)有簡(jiǎn)單的方法可以在不影響性能的情況下逐個(gè)字符地遍歷我的樹(shù)。如果只有一種方法可以一次跨越數(shù)組中的多個(gè)內(nèi)存地址,就像您可以在 C++ 中使用一些指針?biāo)惴ㄒ粯?.....除了有......(歸功于@Ivan Stoev 的評(píng)論)
解決方案
解決方案是使用System.ReadOnlySpan<T>(不可能是System.Span<T>因?yàn)樽址遣豢勺兊模渌?,它允許我們?cè)诓粍?chuàng)建副本的情況下讀取現(xiàn)有數(shù)組中內(nèi)存地址的子數(shù)組。
這段代碼發(fā)布:
string _s1 = s1.Substring(i, j);
if (stree.has(_s1))
{
score += j - i;
longest = j - i;
}
更改為以下內(nèi)容:
if (stree.has(i, j))
{
score += j - i;
longest = j - i;
}
哪里stree.has()現(xiàn)在需要兩個(gè)整數(shù)(子字符串的位置和長(zhǎng)度)并執(zhí)行:
ReadOnlySpan<char> substr = s1.AsSpan(i, j);
請(qǐng)注意,substr變量實(shí)際上是對(duì)初始s1數(shù)組字符子集的引用,而不是副本?。ㄔ搒1變量已可從此函數(shù)訪問(wèn))
請(qǐng)注意,在撰寫(xiě)本文時(shí),我使用的是 C#7.2 和 .NET Framework 4.6.1,這意味著要獲得 Span 功能,我必須轉(zhuǎn)到 Project > Manage NuGet Packages,勾選“Include prerelease”復(fù)選框并瀏覽 System .內(nèi)存并安裝它。
重新運(yùn)行初始測(cè)試(在長(zhǎng)度為 100 萬(wàn)個(gè)字符的字符串上,即 1MB)速度從 2+ 分鐘(我在 2 分鐘后放棄等待)增加到 ~86 毫秒!!
- 1 回答
- 0 關(guān)注
- 230 瀏覽
添加回答
舉報(bào)